STC8H试验箱例程29红外遥控接收解码,使用CosyOS实现
实验功能:
解析红外信号,并且通过数码管显示用户码和键码;
迁移思路:
数码管显示发送数据还是放在滴答钩子中;
使用定时器1产生100us的定时时间,定时中断中采样红外信号接收引脚,当采样结束后发送二值信号量同步led任务来更新显示;
代码实现:
init_hook.c
- /**************************************************************************//**
- * @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"
- #include "..\User\nec.h"
-
- #define BAUD 115200 // 声明串口波特率
- #define TM2 (65536 - SYSCFG_SYSCLK / 4 / BAUD) // 串口波特率发生器的定时器值
-
- 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)
- {
- initGPIO();
-
- AUXR = 0x00; // 允许访问内部xdata
- /*
- 1000 0001
- B7:1:使能访问XFR
- B0:1:P46,P47 位串口二的 RX和TX
- */
- P_SW2 = EAXFR | 0x01; // 1000 0001 允许访问扩展RAM区特殊功能寄存器, 我是用的是STCH试验箱,因此这里需要切换串口二的引脚;
-
- TMOD = 0x00; // 定时器0、1 为16位自动重装载模式
-
- /*
- 0100 0101:
- B7:0:设置定时器0为系统时钟12分频;
- B6:1:设置定时器1为系统时钟,不分频;
- B2:1:设置定时器2为1T模式;
- B0:1:串口1使用定时器2作为波特率发生器;
- */
- AUXR = 0x45; // 0100 0101 定时器1、2为1T模式, 串口1用定时器2做波特率发生器
- /*
- 0100 0000
- B7-B6: 设置串口1为可变波特率8位数据模式
- B4:设置串口1禁止串口1接收;
- B1-B0:串口1的中断标志位
- */
- SCON = 0x40; // 串口1工作模式为模式1
- TI = 1; // 用于printf
-
- /*
- 1100 0000
- B7-B6: 串口1切换至P4.3/P4.4
- */
- P_SW1 = 0xC0;
-
- /*
- 串口2的设置:
- 0100 0000
- B7:0:设置串口2为可变波特率8位数据模式;
- B1-B0:设置串口2中断标志位
- */
- S2CON = 0x40; // 串口2工作模式为模式0,串口2用定时器2做波特率发生器
-
- /* 定时器2 */
- T2L = (unsigned char)TM2;
- T2H = (unsigned char)(TM2 >> 8);
-
- /*
- 0100 0101 | 0001 0000 = 0101 0101
- B4:1:定时器2的运行控制位,这里开启定时器2
- */
- AUXR |= T2R;
- /* UART2中断优先级为1级 */
- IP2H &=~PS2H;
- IP2 |= PS2;
- /* INT0中断优先级为0级 */
- IPH &=~PX0H;
- PX0 = 0;
- /* 任务管理器 */
- #if SYSCFG_DEBUGGING == 1
- S2CON |= S2REN;
- IE2 |= ES2;
- #endif
-
- sampleInit();
- }
复制代码
滴答钩子:tick_hook.c
- /**************************************************************************//**
- * @item CosyOS-II Hook
- * @file tick_hook.c
- * @brief 滴答钩子
- * @detail 每个系统滴答周期,在系统滴答中断中都会被调用一次,
- 适用于每滴答周期/秒/分/时/日/月/年/...做一次的工作。
- * @note 1. 如果您在滴答钩子中调用服务,应调用滴答API。
- 2. 如果您在滴答钩子中调用自定义函数并且您的MCU内核为8051,自定义函数
- 可能需要添加using属性、或声明为相对寄存器访问。
- demo1:
- void your_function(void) MCUCFG_C51USING {... ...}
-
- demo2:
- #pragma NOAREGS
- void your_function(void) {... ...}
- #pragma AREGS
- * @author 迟凯峰
- * @version V3.1.0
- * @date 2024.11.26
- ******************************************************************************/
-
- #include "..\System\os_link.h"
- #include "..\User\led.h"
- #if SYSCFG_TICKHOOK == __ENABLED__
-
- void tick_hook(void) MCUCFG_C51USING
- {
- if(true){ /* 每滴答周期执行一次 */
- sendData();
- }
- #if SYSCFG_SOFTRTC == __ENABLED__
- if(s_sign_every.halfsec){
- s_sign_every.halfsec = false;
- if(true){ /* 每半秒执行一次(每半秒,first tick)*/
- }
- if(s_sign_every.second){
- s_sign_every.second = false;
- if(true){ /* 每秒钟执行一次(每秒,first tick)*/
- }
- if(s_sign_every.minute){
- s_sign_every.minute = false;
- if(true){ /* 每分钟执行一次(每分0秒,first tick)*/
-
- }
- if(s_sign_every.hour){
- s_sign_every.hour = false;
- if(true){ /* 每小时执行一次(每时0分0秒,first tick)*/
-
- }
- if(s_sign_every.day){
- s_sign_every.day = false;
- if(true){ /* 每天执行一次(每天0时0分0秒,first tick)*/
-
- }
- if(s_sign_every.month){
- s_sign_every.month = false;
- if(true){ /* 每月执行一次(每月1日0时0分0秒,first tick)*/
-
- }
- if(s_sign_every.year){
- s_sign_every.year = false;
- if(true){ /* 每年执行一次(每年1月1日0时0分0秒,first tick)*/
-
- }
- }
- }
- }
- }
- }
- }
- }
- #endif
- }
-
- #endif
复制代码
LED 显示模块 led.c
-
-
- #include "..\System\os_link.h"
- #include "..\User\led.h"
- #include "..\User\nec.h"
-
- #define DIS_DOT 0x20 // 0010 0000,
- #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] = {DIS_,DIS_,DIS_,DIS_,DIS_BLACK,DIS_BLACK,DIS_,DIS_};
-
-
- void sendData(void) MCUCFG_C51USING {
- static s_u8_t display_index = 0;
- P7 = ~T_COM[7-display_index];
- P6 = ~t_display[LED8[display_index]];
- if(++display_index >= 8)
- {
- display_index = 0; // 循环显示
- }
- }
-
- uCreateTask(led_task, 4, 128, 0, 0)
- {
- s_u16_t UserCode;
- s_u8_t IR_code;
-
- if(uTakeBin(bin_1, ~0))
- {
- UserCode = getUserCode();
- LED8[0] = (s_u8_t)((UserCode >> 12) & 0x0f); //用户码高字节的高半字节
- LED8[1] = (s_u8_t)((UserCode >> 8) & 0x0f); //用户码高字节的低半字节
- LED8[2] = (s_u8_t)((UserCode >> 4) & 0x0f); //用户码低字节的高半字节
- LED8[3] = (s_u8_t)(UserCode & 0x0f); //用户码低字节的低半字节
-
- IR_code = getIRCode();
- LED8[6] = IR_code >> 4;
- LED8[7] = IR_code & 0x0f;
- }
-
-
-
- uEndTasking;
- }
复制代码
NEC 红外信号解析模块 nec.c
-
- #include "..\System\os_link.h"
- #include "..\User\nec.h"
-
- #define Sap_Tick 10000 // 采样频率,一秒钟进行这些次采样, 一次100us
- #define TM1 (65536 - ((SYSCFG_SYSCLK + Sap_Tick/2) / Sap_Tick))
-
- /************* 红外接收程序变量声明 **************/
- sbit P_IR_RX = P3^5; //定义红外接收输入IO口
-
- s_u8_t IR_SampleCnt; //采样计数
- s_u8_t IR_BitCnt; //编码位数
- s_u8_t IR_UserH; //用户码(地址)高字节
- s_u8_t IR_UserL; //用户码(地址)低字节
- s_u8_t IR_data; //数据原码
- s_u8_t IR_DataShit; //数据移位
-
- bit P_IR_RX_temp; //Last sample
- bit B_IR_Sync; //已收到同步标志
- bit B_IR_Press; //红外接收标志
- s_u8_t IR_code; //红外键码
- s_u16_t UserCode; //用户码
-
- uCreateBin(bin_1, 0);
-
- s_u16_t getUserCode(void) {
- return UserCode;
- }
-
- s_u8_t getIRCode(void) {
- return IR_code;
- }
-
- void sampleInit(void) {
- TH1 = (s_u8_t)(TM1 / 256);
- TL1 = (s_u8_t)(TM1 % 256);
- ET1 = 1; //Timer1 interrupt enable
- TR1 = 1; //Tiner1 run
- }
-
-
- //*********************** IR Remote Module **************************
- //this programme is used for Receive IR Remote (NEC Code).
-
- //data format: Synchro, AddressH, AddressL, data, /data, (total 32 bit).
-
- //send a frame(85ms), pause 23ms, send synchro of continue frame, pause 94ms
-
- //data rate: 108ms/Frame
-
-
- //Synchro: low=9ms, high=4.5 / 2.25ms, low=0.5626ms
- //Bit0: high=0.5626ms, low=0.5626ms
- //Bit1: high=1.6879ms, low=0.5626ms
- //frame rate = 108ms ( pause 23 ms or 96 ms)
-
- /******************** 红外采样时间宏定义, 用户不要随意修改 *******************/
-
- #define D_IR_sample 100 //定义采样时间,在60us~250us之间
- #define D_IR_SYNC_MAX (15000/D_IR_sample) //SYNC max time
- #define D_IR_SYNC_MIN (9700 /D_IR_sample) //SYNC min time
- #define D_IR_SYNC_DIVIDE (12375/D_IR_sample) //decide data 0 or 1
- #define D_IR_DATA_MAX (3000 /D_IR_sample) //data max time
- #define D_IR_DATA_MIN (600 /D_IR_sample) //data min time
- #define D_IR_DATA_DIVIDE (1687 /D_IR_sample) //decide data 0 or 1
- #define D_IR_BIT_NUMBER 32 //bit number
-
-
- void IR_RX_NEC(void)
- {
- s_u8_t SampleTime;
-
- IR_SampleCnt++; //Sample + 1
-
- F0 = P_IR_RX_temp; //Save Last sample status
- P_IR_RX_temp = P_IR_RX; //Read current status
- if(F0 && !P_IR_RX_temp) //Pre-sample is high,and current sample is low, so is fall edge
- {
- SampleTime = IR_SampleCnt; //get the sample time
- IR_SampleCnt = 0; //Clear the sample counter
-
- if(SampleTime > D_IR_SYNC_MAX)
- {
- B_IR_Sync = 0; // large the Maxim SYNC time, then error
- }
- else if(SampleTime >= D_IR_SYNC_MIN) //SYNC
- {
- if(SampleTime >= D_IR_SYNC_DIVIDE)
- {
- B_IR_Sync = 1; //has received SYNC
- IR_BitCnt = D_IR_BIT_NUMBER; //Load bit number
- }
- }
- else if(B_IR_Sync) //has received SYNC
- {
- if(SampleTime > D_IR_DATA_MAX)
- {
- B_IR_Sync=0; //data samlpe time too large
- }
- else
- {
- IR_DataShit >>= 1; //data shift right 1 bit
- if(SampleTime >= D_IR_DATA_DIVIDE)
- {
- IR_DataShit |= 0x80; //devide data 0 or 1
- }
- if(--IR_BitCnt == 0) //bit number is over?
- {
- B_IR_Sync = 0; //Clear SYNC
- if(~IR_DataShit == IR_data) //判断数据正反码
- {
- UserCode = ((s_u16_t)IR_UserH << 8) + IR_UserL;
- IR_code = IR_data;
- iGiveBin(bin_1);
- // B_IR_Press = 1; //数据有效
- }
- }
- else if((IR_BitCnt & 7)== 0) //one byte receive
- {
- IR_UserL = IR_UserH; //Save the User code high byte
- IR_UserH = IR_data; //Save the User code low byte
- IR_data = IR_DataShit; //Save the IR data byte
- }
- }
- }
- }
- }
-
-
- /********************** Timer0中断函数 ************************/
- void sample (void) interrupt 3
- {
- IR_RX_NEC();
- }
复制代码
效果展示:
|