09数码管课后小练 简易10秒免单计数器 感谢国芯公司,已收到AI8051u试验箱。
此代码借鉴了坛友silas***的代码:
io.c
- #include "io.h"
- #include "task.h"
- u8 SEG_NUM[] =
- {
- 0x3F, /*'0', 0*/
- 0x06, /*'1', 1*/
- 0x5B, /*'2', 2*/
- 0x4F, /*'3', 3*/
- 0x66, /*'4', 4*/
- 0x6D, /*'5', 5*/
- 0x7D, /*'6', 6*/
- 0x07, /*'7', 7*/
- 0x7F, /*'8', 8*/
- 0x6F, /*'9', 9*/
- 0x77, /*'A', 10*/
- 0x7C, /*'B', 11*/
- 0x39, /*'C', 12*/
- 0x5E, /*'D', 13*/
- 0x79, /*'E', 14*/
- 0x71, /*'F', 15*/
- 0x40, /*'-', 16*/
- 0x00, /*' ', 17*/
- 0x80, /*'.', 18*/
-
- };
-
- u8 T_NUM[8] =
- {
- 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
- };
-
-
-
- u16 Key_Vol = 0; //按键按下持续时间(几个十秒)
-
-
- //------------------------------------595函数定义-------------------------------------------------
- void Init_595(void)
- {
- HC595_SER = 0;
- HC595_RCK = 0;
- HC595_SCK = 0;
- }
-
- void Send_595( u8 dat )
- {
- u8 i;
- for( i=0; i<8; i++ )
- {
- dat <<= 1; //数值左移一位
- HC595_SER = CY; //数据写到引脚
- HC595_SCK = 1; //输出上升沿的时钟信号
- HC595_SCK = 0;
- }
- }
-
- void Display_Seg( u8 HC595_1,u8 HC595_2)
- {
- Send_595(HC595_1); //数码管段码输出 高电平点亮
- Send_595(HC595_2); //数码管位码输出 低电平点亮
-
- HC595_RCK = 1; //数据输出
- HC595_RCK = 0;
- }
-
- u8 Seg_no = 0;
- u8 Seg_no_1 = 0;
- u8 shi = 0;
- u8 fen = 0;
- u8 miao = 0;
- u8 ms_10 =0;
- u8 Run = 0;
- //u8 Key_Vol =0;
- bit win = 0;
- bit key_Start =1;
- u8 Key_Tabe =0;
-
-
- //计时函数
- void TIMECOUNT_Task(void)
- {
- if(key_Start==0)
- {
- ms_10 ++;
- if( ms_10>100 )
- {
- ms_10 = 0;
- miao++;
- if(miao>15)
- {
- miao = 0;
- }
- }
- }
- }
- /**
- * 10秒抢答模式显示函数
- * 功能:特殊显示模式,固定前缀"10:00.",后4位显示当前秒和毫秒
- * 用途:用于抢答场景,直观展示10秒倒计时窗口
- */
- /**
- * 10秒抢答模式显示函数(仅用if-else实现)
- * 功能:特殊显示模式,固定前缀"10:00.",后4位显示当前秒和毫秒
- */
- void Seg_Task_1(void)
- {
- switch(Seg_no){
- case 0: Display_Seg( SEG_NUM[1], ~T_NUM[0] ); break;//小时十位
- case 1: Display_Seg( SEG_NUM[0]|SEG_NUM[18], ~T_NUM[1] ); break;
- case 2: Display_Seg( SEG_NUM[0], ~T_NUM[2] ); break;
- case 3: Display_Seg( SEG_NUM[0], ~T_NUM[3] ); break;
- case 4: Display_Seg( SEG_NUM[miao/10], ~T_NUM[4] ); break;
- case 5: Display_Seg( SEG_NUM[miao%10]|SEG_NUM[18], ~T_NUM[5] ); break;
- case 6: Display_Seg( SEG_NUM[ms_10/10], ~T_NUM[6] ); break;
- case 7: Display_Seg( SEG_NUM[ms_10%10], ~T_NUM[7] ); break;
- }
-
- Seg_no++;
- if(Seg_no>7){
- Seg_no=0;
- }
-
- }
-
-
- u8 state_now = 0;
-
-
- //u8 Seg_no=0;
-
-
-
- /*课后小练:简易10秒免单计数器.
- 1.在前四位数码管上显示目标时间,即“ 10. 00 ”表示定时时间10秒钟
- 2.后四位显示当前的计时00.00,最小单位为10msBuild started: Project: demo
-
- 3.按下开始按钮后,每10ms最末尾的数字+1;直到按下结束按钮后停止计数。
- */
- //按键处理任务
-
- void KEY_Task(void)
- {
- if( P34 == 0) //检测到P34按键按下
- {
- Key_Vol++; //消抖计数累加
- if( Key_Vol == 5) //连续检测到5次低电平(消抖完成)
- {
- if(key_Start ==1) // 当前是暂停状态,则切换到运行
- {
- key_Start = 0;
- }
- else if(key_Start == 0) //// 当前是运行状态,则切换到暂停
- {
- key_Start = 1;
- // 判断是否在9.5-10.5秒之间按下,满足则判定为胜利
- if((miao == 10 && ms_10 > 50) || (miao == 9 && ms_10 > 50))
- {
- win = 1;
-
- }
- }
- }
- }
- else if(P33 == 0) // 检测到P33按键按下(复位键)
- {
- Key_Vol++;
- if(Key_Vol == 5) // 消抖完成
- {
- key_Start = 1; // 暂停计时
- ms_10 = 0; // 重置毫秒
- miao = 0; // 重置秒
- win = 0; // 清除胜利标志
- P0 = 0xFF; // 关闭P0口控制的LED
- }
-
- }
- else
- {
- Key_Vol = 0;
- }
- }
- /**
- * 胜利效果展示函数
- * 功能:当win=1时,P0口8个LED依次点亮(流水灯效果)
- */
- u8 led_eff=0;
- void win_effect(void)
- {
- if(win == 1) // 胜利状态
- {
- P0 =~T_NUM[led_eff]; // 点亮当前LED(低电平有效,取反后对应位为0)
- led_eff++; // 切换到下一个LED
- if(led_eff > 7)
- {
-
- led_eff = 0; // 循环显示
- }
- }
- }
-
- void PLED_40(void)
- {
- u8 cod[8];
- cod[0] = 0x0f; //表示开启P0-P3
- cod[1] = 0x01; //P0端口
- cod[2] = 0x01; //P1
- cod[3] = ~T_NUM[state_now]; //P2
- cod[4] = 0x01; //P3
- LED40_SendData( cod, 5 );
-
- P2 = ~T_NUM[state_now];
- state_now++;
- if(state_now > 7)
- state_now = 0;
-
- }
-
- void SEG_PC(void)
- {
- u8 cod[8];
-
- cod[0] = SEG_NUM[shi/10]; //数码管小时十位数段码
- cod[1] = SEG_NUM[shi%10]; //小时的个位
- cod[2] =SEG_NUM[16]; //第一个横杠
-
- cod[3] = SEG_NUM[fen/10]; //数码管分钟十位数段码
- cod[4] = SEG_NUM[fen%10]; //分钟的个位
- cod[5] =SEG_NUM[16]; //第二个横杠
-
- cod[6] = SEG_NUM[miao/10]; //数码管秒十位数段码
- cod[7] = SEG_NUM[miao%10]; //秒的个位
-
- SEG7_ShowCode(cod);
- }
复制代码
io.h
- #ifndef __IO_H
- #define __IO_H
-
- #include "config.h" //调用头文件
-
- //定义引脚名称
- #define HC595_SER P34
- #define HC595_RCK P35
- #define HC595_SCK P32
-
-
-
- void Key_Task(void);
-
- //--------------------------------------------------74HC595控制函数声明-----------------------------------------------------
- void Init_595(void);
- void Send_595( u8 dat );
- void Display_Seg( u8 HC595_1,u8 HC595_2);
- //void Seg_Task(void);
- void TIMECOUNT_Task(void);
- void PLED_40(void);
- void SEG_PC(void);
- void KEY_Task(void);
-
- void Seg_Task_1(void);
- void win_effect(void);
-
- #endif
复制代码
task.c
- #include "task.h"
- #include "io.h"
-
- //========================================================================
- // 本地变量声明
- //========================================================================
-
- static TASK_COMPONENTS Task_Comps[]=
- {
- //状态 计数 周期 函数
-
-
- // {0, 10, 10, Key_Task}, /* task 1 Period: 50ms */
- // {0, 1, 1, Seg_Task}, /* task 1 Period: 1ms */
- {0, 10, 10, TIMECOUNT_Task}, /* task 1 Period: 1000ms */
- // {0, 1000, 1000, PLED_40}, /* task 1 Period: 500ms */
- // {0, 1, 1, SEG_PC}, /* task 1 Period: 1ms */
- {0, 10, 10, KEY_Task}, /* task 1 Period: 1000ms */
- {0, 1, 1, Seg_Task_1}, /* task 1 Period: 1ms */
- {0, 500, 200, win_effect}, /* task 1 Period: 1ms */
-
- };
-
- u8 Tasks_Max = sizeof(Task_Comps)/sizeof(Task_Comps[0]);
-
- //========================================================================
- // 函数: Task_Handler_Callback
- // 描述: 任务标记回调函数.
- // 参数: None.
- // 返回: None.
- // 版本: V1.0, 2012-10-22
- //========================================================================
- void Task_Marks_Handler_Callback(void)
- {
- u8 i;
- for(i=0; i<Tasks_Max; i++)
- {
- if(Task_Comps[i].TIMCount) /* If the time is not 0 */
- {
- Task_Comps[i].TIMCount--; /* Time counter decrement */
- if(Task_Comps[i].TIMCount == 0) /* If time arrives */
- {
- /*Resume the timer value and try again */
- Task_Comps[i].TIMCount = Task_Comps[i].TRITime;
- Task_Comps[i].Run = 1; /* The task can be run */
- }
- }
- }
- }
-
- //========================================================================
- // 函数: Task_Pro_Handler_Callback
- // 描述: 任务处理回调函数.
- // 参数: None.
- // 返回: None.
- // 版本: V1.0, 2012-10-22
- //========================================================================
- void Task_Pro_Handler_Callback(void)
- {
- u8 i;
- for(i=0; i<Tasks_Max; i++)
- {
- if(Task_Comps[i].Run) /* If task can be run */
- {
- Task_Comps[i].Run = 0; /* Flag clear 0 */
- Task_Comps[i].TaskHook(); /* Run task */
- }
- }
- }
-
复制代码
main.c
- #include "config.h"
- #include "task.h"
- #include "io.h"
-
-
-
- char *USER_DEVICEDESC = NULL;
- char *USER_PRODUCTDESC = NULL;
- char *USER_STCISPCMD = "@STCISP#";
-
-
- //void Delay10ms(void) //@24.000MHz
- //{
- // unsigned long edata i;
-
- // _nop_();
- // _nop_();
- // i = 119998UL;
- // while (i) i--;
- //}
- void main(void)
- {
- //int count=1; //按键计数变量
-
- Sys_init(); //系统初始化(调用函数)
- usb_init(); //USB CDC 接口配置
-
- IE2 |= 0x80; //使能USB中断
- Timer0_Init(); //定时器初始化
- Init_595(); //595端口电平初始化
- EA = 1; //IE |= 0X80;
-
- P40=0;
-
- while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
-
- while(1)
- {
-
- if (bUsbOutReady) //如果接收到了数据
- {
- //USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
-
- usb_OUT_done(); //
- }
- Task_Pro_Handler_Callback(); //执行函数
-
-
-
- }
- }
- void Timer0_Isr(void) interrupt 1
- {
-
- Task_Marks_Handler_Callback(); //系统计时
-
- }
复制代码
09shu码管 10秒简易计数器.rar
(202.48 KB, 下载次数: 1)
|