综合实验——165、595、计数器秒表
2008-03-24 16:22
330 查看
实验描述:
利用计数器中断做秒表程序,再利用165芯片读取当前的按键状态,然后利用595芯片将当前时间显示到八位数码管上 。并且随时响应用户的按键行为。
代码优点:可防止用户按键时间过长而误判。
代码缺点:暂停与开始功能彻底阻断了所有中断。使得秒表在暂停的时候无法响应任何中断。
#include <iom8v.h>
#include <macros.h>
/**//*******************************
* PC0 -------- M595_SER *
* PC1 -------- M595_SRCLK *
* PC2 -------- M595_RCLK *
* PC3 --------- M165_PL *
* PC4 ---------- M165_CP *
* PC5 ---------- M165_Q7 *
* PD0~3 -------- G1~4 *
* K1~K2 -------- M165_D0 ~ D1 *
* a~h ----------- M595_Q0 ~ Q7 *
*******************************/
#define M165_CP_LOW (PORTC &= ~BIT(PC4))
#define M165_CP_HIGH (PORTC |= BIT(PC4))
#define M165_PL_LOW (PORTC &= ~BIT(PC3))
#define M165_PL_HIGH (PORTC |= BIT(PC3))
#define M165_Q7 ((PINC & BIT(PC5)) ? BIT(0) : 0x00)
#define M595_SER_HIGH (PORTC |= BIT(PC0))
#define M595_SER_LOW (PORTC &= ~BIT(PC0))
#define M595_SRCLK_HIGH (PORTC |= BIT(PC1))
#define M595_SRCLK_LOW (PORTC &= ~BIT(PC1))
#define M595_RCLK_HIGH (PORTC |= BIT(PC2))
#define M595_RCLK_LOW (PORTC &= ~BIT(PC2))
#define LED_BIT_SELECT PORTD
#define KEY1_UP(n) ((n & BIT(0)) ? 0x01 : 0x00)
#define KEY1_DOWN(n) ((n & BIT(0)) ? 0x00 : 0x01)
#define KEY2_UP(n) ((n & BIT(1)) ? 0x01 : 0x00)
#define KEY2_DOWN(n) ((n & BIT(1)) ? 0x00: 0x01)
UINT16 LED_TEXT[24] = ...{0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71,
0x73, 0x38, 0x76, 0x3E, 0x50, 0x08, 0x40, 0x00};
//8位数码管的24种状态。0-9分别代表了十个数字的代码
#pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF
UINT16 g_Time_Count; //时间数
void Count_Increase(void) //时间增加函数
...{
g_Time_Count++;
if(g_Time_Count > 9999)
...{
g_Time_Count = 0;
}
}
void Count_Clear(void) //时间清空函数
...{
timer0_init(); //计数器复位
g_Time_Count = 0; //时间清零
}
void Pause_Or_Start(void) //暂停或者继续
...{
static UINT8 state = 0;
state = !state;
if (state)
...{
CLI();
}
else
...{
SEI();
}
}
void timer0_ovf_isr(void)
...{
static UINT16 wCount = 0;
TCNT0 = 0x83; //reload counter value
if(wCount >= 1000)
...{
wCount = 0;
Count_Increase();
}
wCount++;
}
void Device_Init(void)
...{
Port_Init();
//stop errant interrupts until set up
CLI(); //disable all interrupts
timer0_init();
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x01; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
void Port_Init(void)
...{
DDRD = 0xFF;
DDRC = ~BIT(PC5);
PORTD = 0xFF;
PORTC = 0xFF;
}
void Delay_MS(UINT16 wTimer)
...{
UINT16 i = 0,j = 0;
for (i = 0;i < wTimer;i++)
...{
for (j = 0;j < 200;j++)
...{;}
}
}
void Show_Led(UINT16 wNum) //将一个四位数显示到四个八位数码管上
...{
UINT8 chBit;
for(chBit = 0x08; chBit > 0; chBit >>= 1) //从个位开始显示
...{
// LED_BIT_DATA = ~LED_TEXT[wNum % 10];
Write_Data_To_595(~LED_TEXT[wNum % 10]); //将数字代码写入595芯片
Show_M595_Data(); //595芯片输出代码
LED_BIT_SELECT = chBit; //选择相应的位
wNum /= 10;
if(wNum == 0)
...{
return;
}
}
}
void M165_Update_Data(void) //给芯片一个上升沿以更新595芯片存储的内容
...{
M165_PL_LOW;
M165_PL_HIGH;
}
UINT8 Read_A_Byte_From_165(void) //从165芯片中读取一个字节的内容
...{
UINT8 chCount = 0;
UINT8 chResult = 0;
M165_PL_HIGH; //拉高PL端
for(chCount = 0; chCount < 8; ++chCount) //依次读取八位数
...{
chResult <<= 1;
chResult |= M165_Q7;
M165_CP_LOW; //给出上升沿以使165移位
NOP();
M165_CP_HIGH;
}
return chResult;
}
void Write_Data_To_595(UINT8 chData) //向595芯片中写入值
...{
UINT8 chCount = 0;
for(chCount = 0; chCount < 8; chCount++) //计数控制
...{
M595_SRCLK_LOW; //拉低SRCLK端
if((chData & BIT(7 - chCount)) != 0x00) //根据当前位的状态将SER端拉高或拉低
...{
M595_SER_HIGH;
}
else
...{
M595_SER_LOW;
}
M595_SRCLK_HIGH; //给出上升沿
}
}
void Show_M595_Data(void) //在RCLK上给上升沿以输出595芯片内容
...{
M595_RCLK_LOW;
NOP();
M595_RCLK_HIGH;
}
void timer0_init(void) //计数器初始化
...{
TCCR0 = 0x00; //stop
TCNT0 = 0x83; //set count
TCCR0 = 0x03; //start timer
}
void main()
...{
UINT8 chKey_State; //当前的所有按键状态
UINT8 chKey_State_Pre = 0xFF; //上次读取的按键状态
g_Time_Count = 0; //时间置零
Device_Init();
while(1)
...{
M165_Update_Data(); //165芯片更新数据
chKey_State = Read_A_Byte_From_165(); //从165芯片中读取数据
if (KEY1_UP(chKey_State_Pre) && KEY1_DOWN(chKey_State)) //如果KEY1刚被按下
...{
Pause_Or_Start(); //执行继续、暂停功能
}
else if(KEY2_UP(chKey_State_Pre) && KEY2_DOWN(chKey_State)) //如果KEY2刚被按下
...{
Count_Clear(); //执行清零功能
}
chKey_State_Pre = chKey_State;
Show_Led(g_Time_Count); //将当前时间显示到数码管
}
}
利用计数器中断做秒表程序,再利用165芯片读取当前的按键状态,然后利用595芯片将当前时间显示到八位数码管上 。并且随时响应用户的按键行为。
代码优点:可防止用户按键时间过长而误判。
代码缺点:暂停与开始功能彻底阻断了所有中断。使得秒表在暂停的时候无法响应任何中断。
#include <iom8v.h>
#include <macros.h>
/**//*******************************
* PC0 -------- M595_SER *
* PC1 -------- M595_SRCLK *
* PC2 -------- M595_RCLK *
* PC3 --------- M165_PL *
* PC4 ---------- M165_CP *
* PC5 ---------- M165_Q7 *
* PD0~3 -------- G1~4 *
* K1~K2 -------- M165_D0 ~ D1 *
* a~h ----------- M595_Q0 ~ Q7 *
*******************************/
#define M165_CP_LOW (PORTC &= ~BIT(PC4))
#define M165_CP_HIGH (PORTC |= BIT(PC4))
#define M165_PL_LOW (PORTC &= ~BIT(PC3))
#define M165_PL_HIGH (PORTC |= BIT(PC3))
#define M165_Q7 ((PINC & BIT(PC5)) ? BIT(0) : 0x00)
#define M595_SER_HIGH (PORTC |= BIT(PC0))
#define M595_SER_LOW (PORTC &= ~BIT(PC0))
#define M595_SRCLK_HIGH (PORTC |= BIT(PC1))
#define M595_SRCLK_LOW (PORTC &= ~BIT(PC1))
#define M595_RCLK_HIGH (PORTC |= BIT(PC2))
#define M595_RCLK_LOW (PORTC &= ~BIT(PC2))
#define LED_BIT_SELECT PORTD
#define KEY1_UP(n) ((n & BIT(0)) ? 0x01 : 0x00)
#define KEY1_DOWN(n) ((n & BIT(0)) ? 0x00 : 0x01)
#define KEY2_UP(n) ((n & BIT(1)) ? 0x01 : 0x00)
#define KEY2_DOWN(n) ((n & BIT(1)) ? 0x00: 0x01)
UINT16 LED_TEXT[24] = ...{0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71,
0x73, 0x38, 0x76, 0x3E, 0x50, 0x08, 0x40, 0x00};
//8位数码管的24种状态。0-9分别代表了十个数字的代码
#pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF
UINT16 g_Time_Count; //时间数
void Count_Increase(void) //时间增加函数
...{
g_Time_Count++;
if(g_Time_Count > 9999)
...{
g_Time_Count = 0;
}
}
void Count_Clear(void) //时间清空函数
...{
timer0_init(); //计数器复位
g_Time_Count = 0; //时间清零
}
void Pause_Or_Start(void) //暂停或者继续
...{
static UINT8 state = 0;
state = !state;
if (state)
...{
CLI();
}
else
...{
SEI();
}
}
void timer0_ovf_isr(void)
...{
static UINT16 wCount = 0;
TCNT0 = 0x83; //reload counter value
if(wCount >= 1000)
...{
wCount = 0;
Count_Increase();
}
wCount++;
}
void Device_Init(void)
...{
Port_Init();
//stop errant interrupts until set up
CLI(); //disable all interrupts
timer0_init();
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x01; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
void Port_Init(void)
...{
DDRD = 0xFF;
DDRC = ~BIT(PC5);
PORTD = 0xFF;
PORTC = 0xFF;
}
void Delay_MS(UINT16 wTimer)
...{
UINT16 i = 0,j = 0;
for (i = 0;i < wTimer;i++)
...{
for (j = 0;j < 200;j++)
...{;}
}
}
void Show_Led(UINT16 wNum) //将一个四位数显示到四个八位数码管上
...{
UINT8 chBit;
for(chBit = 0x08; chBit > 0; chBit >>= 1) //从个位开始显示
...{
// LED_BIT_DATA = ~LED_TEXT[wNum % 10];
Write_Data_To_595(~LED_TEXT[wNum % 10]); //将数字代码写入595芯片
Show_M595_Data(); //595芯片输出代码
LED_BIT_SELECT = chBit; //选择相应的位
wNum /= 10;
if(wNum == 0)
...{
return;
}
}
}
void M165_Update_Data(void) //给芯片一个上升沿以更新595芯片存储的内容
...{
M165_PL_LOW;
M165_PL_HIGH;
}
UINT8 Read_A_Byte_From_165(void) //从165芯片中读取一个字节的内容
...{
UINT8 chCount = 0;
UINT8 chResult = 0;
M165_PL_HIGH; //拉高PL端
for(chCount = 0; chCount < 8; ++chCount) //依次读取八位数
...{
chResult <<= 1;
chResult |= M165_Q7;
M165_CP_LOW; //给出上升沿以使165移位
NOP();
M165_CP_HIGH;
}
return chResult;
}
void Write_Data_To_595(UINT8 chData) //向595芯片中写入值
...{
UINT8 chCount = 0;
for(chCount = 0; chCount < 8; chCount++) //计数控制
...{
M595_SRCLK_LOW; //拉低SRCLK端
if((chData & BIT(7 - chCount)) != 0x00) //根据当前位的状态将SER端拉高或拉低
...{
M595_SER_HIGH;
}
else
...{
M595_SER_LOW;
}
M595_SRCLK_HIGH; //给出上升沿
}
}
void Show_M595_Data(void) //在RCLK上给上升沿以输出595芯片内容
...{
M595_RCLK_LOW;
NOP();
M595_RCLK_HIGH;
}
void timer0_init(void) //计数器初始化
...{
TCCR0 = 0x00; //stop
TCNT0 = 0x83; //set count
TCCR0 = 0x03; //start timer
}
void main()
...{
UINT8 chKey_State; //当前的所有按键状态
UINT8 chKey_State_Pre = 0xFF; //上次读取的按键状态
g_Time_Count = 0; //时间置零
Device_Init();
while(1)
...{
M165_Update_Data(); //165芯片更新数据
chKey_State = Read_A_Byte_From_165(); //从165芯片中读取数据
if (KEY1_UP(chKey_State_Pre) && KEY1_DOWN(chKey_State)) //如果KEY1刚被按下
...{
Pause_Or_Start(); //执行继续、暂停功能
}
else if(KEY2_UP(chKey_State_Pre) && KEY2_DOWN(chKey_State)) //如果KEY2刚被按下
...{
Count_Clear(); //执行清零功能
}
chKey_State_Pre = chKey_State;
Show_Led(g_Time_Count); //将当前时间显示到数码管
}
}
相关文章推荐
- cisco路由器综合实验之四 动态路由协议(rip路由协议)
- 线性表综合实验——静态链表
- java实验四 面向对象的综合应用
- 路由器和交换机的综合实验
- 定时器/计数器实验报告
- 路由交换综合实验(用HSRP、OSPF、VTP、DHCP、ACL等)
- 定时器/计数器实验报告
- 组播综合实验--SSM,SM,URD
- 《网络基础》- 第6集-用PacketTracer实现网络基础综合实验
- 嵌入式实验报告(OK6410环境下的设备驱动及进程间通信 综合实验)
- RIP和OSPF双点双向重发布_综合实验
- 实验二 线性表综合实验之《双链表》
- 线性表综合实验之顺序表
- 网络综合实验案例
- 第2次实验——算法基本功 与 综合思考
- 第2次实验——算法基本功 与 综合思考
- 第2次实验——算法基本功 与 综合思考
- 第2次实验——算法基本功 与 综合思考
- : 第2次实验——算法基本功 与 综合思考
- 第2次实验——算法基本功 与 综合思考