STC8试验箱例程16 用CosyOS实现
例程16的功能是:
1、模拟RTC显示时分;
2、行列扫描方式实现检测矩阵键盘更新时间;
3、数码管显示时间和按键值;
思路:
三个功能分别对应三个任务:
1、rtc_task:用来延时500ms,循环执行,执行过程中调用display_task 提供的修改显示缓存的函数;
2、display_task:延时1ms 通过P6,P7发送显示数据到595, 并且提供刷新显示缓存函数;
3、key_task:用来检测按键,调用led 提供的修改显示缓存函数修改按键显示值和时间显示;
步骤:
1、 按照迟老师教程搭建工程,也可以复制之前的工程,修改内容;
2、添加 lec.c , led.h、key.c、key.h、 rtc.h、rtc.c:
内容如下:
led.c:
-
-
- #include "..\System\os_link.h"
- #include "..\User\led.h"
-
- #define DIS_DOT 0x20
- #define DIS_BLACK 0x10
- #define DIS_ 0x11
-
- s_u8_t code t_display[]={ //标准字库
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
- //black - H J K L N o P U t G Q r M y
- 0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
- 0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
-
- s_u8_t code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
-
-
- s_u8_t LED8[8]; //显示缓冲
- s_u8_t display_index; //显示位索引
-
- uCreateTask(display_task, 6, 32, 0 ,0 ) { // 创建任务,名称为display_task,优先级为6,给定任务栈大小为32字节;
-
- s_u8_t i;
- for(i=0; i<8; i++) {
- LED8[i] = 0x10; //上电消隐
- }
- display_index = 0;
- refreshDisplay(12, 30, 0);
-
- while (1) {
-
- P7 = ~T_COM[7-display_index];
- P6 = ~t_display[LED8[display_index]];
- if(++display_index >= 8) {
- display_index = 0; //8位结束回0
- }
-
- uDelay_ms(1); // 1毫秒延时, 延时时间到后发送数据到595
- }
-
-
- uEndTasking;
-
- }
-
- void refreshDisplay(s_u8_t hour, s_u8_t minute, s_u16_t msecond) {
- if(hour >= 10) {
- LED8[0] = hour / 10;
- }
- else {
- LED8[0] = DIS_BLACK;
- }
- LED8[1] = hour % 10;
- LED8[2] = minute / 10;
- LED8[3] = minute % 10;
- if(msecond >= 500) {
- LED8[1] |= DIS_DOT; //小时后的小数点做秒闪
- }
- }
-
- void showKeyCode(s_u8_t keyCode) {
- LED8[6] = keyCode / 10; //显示键码
- LED8[7] = keyCode % 10; //显示键码
- }
复制代码
led.h
- #ifndef __LED_H
- #define __LED_H
-
- uExternTask(display_task);
-
- void showKeyCode(s_u8_t keyCode);
- void refreshDisplay(s_u8_t hour, s_u8_t minute, s_u16_t msecond);
-
- #endif
复制代码
rtc.c
- #include "..\System\os_link.h"
- #include "..\User\rtc.h"
- #include "..\User\led.h"
-
- s_u8_t hour,minute,second; //RTC变量
- s_u16_t msecond;
-
- void RTC(void)
- {
- if(++second >= 60)
- {
- second = 0;
- if(++minute >= 60)
- {
- minute = 0;
- if(++hour >= 24) {
- hour = 0;
- }
- }
- }
- }
-
- uCreateTask(rtc_task, 5, 32, 0, 0) {
- hour = 12;
- minute = 0;
- second = 0;
- msecond = 0;
- while(1) {
- msecond += 500;
- if(msecond >= 1000) {
- msecond = 0;
- RTC();
- }
-
- refreshDisplay(hour, minute, msecond);
-
- uDelay_ms(500);
- }
-
- uEndTasking;
- }
-
- void addHour(void) {
- if(++hour >= 24) {
- hour = 0;
- }
-
- refreshDisplay(hour, minute, msecond);
- }
-
-
- void decHour(void) {
- if(--hour >= 24) {
- hour = 23;
- }
- refreshDisplay(hour, minute, msecond);
- }
-
- void addMin(void) {
- second = 0;
- if(++minute >= 60) {
- minute = 0;
- }
- }
-
- void decMin(void) {
- second = 0;
- if(--minute >= 60) { // 这里就很巧妙,利用溢出
- minute = 59;
- }
- }
-
复制代码
rtc.h
- #ifndef __RTC_H
- #define __RTC_H
-
- void addHour(void);
- void decHour(void);
- void addMin(void);
- void decMin(void);
- void RTC(void);
- uExternTask(rtc_task);
-
- #endif
复制代码
key.c
- #include "..\System\os_link.h"
- #include "..\User\rtc.h"
- #include "..\User\key.h"
- #include "..\User\led.h"
-
- s_u8_t KeyCode; //给用户使用的键码, 1~16有效
-
- s_u8_t IO_KeyState, IO_KeyState1, IO_KeyHoldCnt; //行列键盘变量
-
- s_u8_t code T_KeyTable[16] = {0,1,2,0,3,0,0,0,4,0,0,0,0,0,0,0};
-
- void IO_KeyDelay(void)
- {
- s_u8_t i;
- i = 60;
- while(--i);
- }
-
- void IO_KeyScan(void) //50ms call
- {
- s_u8_t j;
-
- j = IO_KeyState1; //保存上一次状态
-
- P0 = 0xf0; //X低,读Y
- IO_KeyDelay();
- IO_KeyState1 = P0 & 0xf0;
-
- P0 = 0x0f; //Y低,读X
- IO_KeyDelay();
- IO_KeyState1 |= (P0 & 0x0f);
- IO_KeyState1 ^= 0xff; //取反
-
- if(j == IO_KeyState1) //连续两次读相等
- {
- j = IO_KeyState;
- IO_KeyState = IO_KeyState1;
- if(IO_KeyState != 0) //有键按下
- {
- F0 = 0;
- if(j == 0) F0 = 1; //第一次按下
- else if(j == IO_KeyState)
- {
- if(++IO_KeyHoldCnt >= 20) //1秒后重键
- {
- IO_KeyHoldCnt = 18;
- F0 = 1;
- }
- }
- if(F0)
- {
- j = T_KeyTable[IO_KeyState >> 4];
- if((j != 0) && (T_KeyTable[IO_KeyState& 0x0f] != 0))
- KeyCode = (j - 1) * 4 + T_KeyTable[IO_KeyState & 0x0f] + 16; //计算键码,17~32
- }
- }
- else IO_KeyHoldCnt = 0;
- }
- P0 = 0xff;
- }
-
-
- uCreateTask(key_task, 4, 32,0 ,0) {
-
- while(1) {
- IO_KeyScan();
-
- if(KeyCode > 0) //有键按下
- {
- showKeyCode(KeyCode);
-
- if(KeyCode == 25) //hour +1
- {
- addHour();
- }
- if(KeyCode == 26) //hour -1
- {
- decHour();
- }
- if(KeyCode == 27) //minute +1
- {
- addMin();
- }
- if(KeyCode == 28) //minute -1
- {
- decMin();
- }
- KeyCode = 0;
- }
-
-
- uDelay_ms(50);
- }
-
- uEndTasking;
-
- }
复制代码
key.h
- #ifndef __KEY_H
- #define __KEY_H
-
- uExternTask(key_task);
-
- #endif
复制代码
3、修改初始化钩子和启动钩子
- /**************************************************************************//**
- * @item CosyOS-II Hook
- * @file init_hook.c
- * @brief 初始化钩子
- * @detail 在主函数中首先被调用,适用于初始化时钟、GPIO、寄存器等工作。
- * @author 迟凯峰
- * @version V3.0.0
- * @date 2024.06.25
- ******************************************************************************/
-
- #include "..\System\os_link.h"
-
- void initGPIO(void) {
- P0M1 = 0x30; P0M0 = 0x30; //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
- P1M0 = 0; P1M1 = 0;
- P2M0 = 0; P2M1 = 0;
- P3M0 = 0; P3M1 = 0;
- P4M0 = 0; P4M1 = 0;
- P5M0 = 0; P5M1 = 0;
- P6M1 = 0xff; P6M0 = 0xff; //设置为漏极开路(实验箱加了上拉电阻到3.3V)
- P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
- }
-
- void init_hook(void)
- {
- #define BAUD 115200 // 串口波特率
- #define TM2 (65536 - SYSCFG_SYSCLK / 4 / BAUD)
-
- initGPIO(); // 初始化GPIO
-
-
- AUXR = 0x00; // 允许访问内部xdata
- P_SW2 = EAXFR | 0x01; // xxxx xxxx = 1000 0000 允许访问扩展RAM区特殊功能寄存器, 我是用的是STCH试验箱,因此这里需要切换串口二的引脚;
-
- TMOD = 0x00; // 定时器0、1、2、3、4为16位自动重装载模式
- AUXR = 0x45; // 定时器1、2为1T模式, 串口1用定时器2做波特率发生器
- SCON = 0x40; // 串口1工作模式为模式1
- S2CON = 0x40; // 串口2工作模式为模式0,串口2用定时器2做波特率发生器
- P_SW1 = 0xC0; // 串口1切换至P4.3/P4.4
- TI = 1; // 用于printf
- /* 定时器2 */
- T2L = (unsigned char)TM2;
- T2H = (unsigned char)(TM2 >> 8);
- AUXR|= T2R;
- /* UART2中断优先级为1级 */
- IP2H &=~PS2H;
- IP2 |= PS2;
- /* INT0中断优先级为0级 */
- IPH &=~PX0H;
- PX0 = 0;
- /* 任务管理器 */
- #if SYSCFG_DEBUGGING == 1
- S2CON |= S2REN;
- IE2 |= ES2;
- #endif
- }
复制代码
效果演示:
|