lzts 发表于 2024-12-2 09:12:40

支持大神原创,助力STC32位8051腾飞

大锤子 发表于 2024-12-2 16:37:48

STC8H试验箱例程29红外遥控接收解码,使用CosyOS实现


实验功能:
解析红外信号,并且通过数码管显示用户码和键码;

迁移思路:
数码管显示发送数据还是放在滴答钩子中;
使用定时器1产生100us的定时时间,定时中断中采样红外信号接收引脚,当采样结束后发送二值信号量同步led任务来更新显示;

代码实现:
init_hook.c
/**************************************************************************//**
* @item   CosyOS-II Hook
* @file   init_hook.c
* @brief    初始化钩子
* @detail   在主函数中首先被调用,适用于初始化时钟、GPIO、寄存器等工作。
* @author   迟凯峰
* @versionV3.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   每个系统滴答周期,在系统滴答中断中都会被调用一次,
             适用于每滴答周期/秒/分/时/日/月/年/...做一次的工作。
* @note1. 如果您在滴答钩子中调用服务,应调用滴答API。
          2. 如果您在滴答钩子中调用自定义函数并且您的MCU内核为8051,自定义函数
             可能需要添加using属性、或声明为相对寄存器访问。
             demo1:
             void your_function(void) MCUCFG_C51USING {... ...}
            
             demo2:
             #pragma NOAREGS
             void your_function(void) {... ...}
             #pragma AREGS
* @author   迟凯峰
* @versionV3.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 = {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;
    P6 = ~t_display];
    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 = (s_u8_t)((UserCode >> 12) & 0x0f);    //用户码高字节的高半字节
                LED8 = (s_u8_t)((UserCode >> 8)& 0x0f);    //用户码高字节的低半字节
                LED8 = (s_u8_t)((UserCode >> 4)& 0x0f);    //用户码低字节的高半字节
                LED8 = (s_u8_t)(UserCode & 0x0f);            //用户码低字节的低半字节
               
                IR_code = getIRCode();
                LED8 = IR_code >> 4;
                LED8 = 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_tIR_SampleCnt;       //采样计数
s_u8_tIR_BitCnt;          //编码位数
s_u8_tIR_UserH;         //用户码(地址)高字节
s_u8_tIR_UserL;         //用户码(地址)低字节
s_u8_tIR_data;            //数据原码
s_u8_tIR_DataShit;      //数据移位

bit P_IR_RX_temp;       //Last sample
bit B_IR_Sync;          //已收到同步标志
bit B_IR_Press;         //红外接收标志
s_u8_tIR_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_tSampleTime;

    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();
}
效果展示:

CosyOS 发表于 2024-12-2 17:19:33

大锤子 发表于 2024-12-2 16:37
STC8H试验箱例程29红外遥控接收解码,使用CosyOS实现




{:4_250:}

jewhying 发表于 2024-12-2 20:39:59

你好,之前8位的stc11芯片的时候用过rtos系统,开发过不少逻辑指令的IO开发板(c)+用AC开发的电阻屏做嵌入式程序(汇编),模拟plc的部分功能,虽然效率够但寄存器不够用了,不是很复杂的功能也不想做扩展,现在准备用液晶+触控8位不够用了,用于机械设备显示,正在学32位的,不知道这个实验板要如何申请获取?就是想捡个现成的,实在申请不到到时候可能也会买一个。

大锤子 发表于 2024-12-2 23:01:07

jewhying 发表于 2024-12-2 20:39
你好,之前8位的stc11芯片的时候用过rtos系统,开发过不少逻辑指令的IO开发板(c)+用AC开发的电阻屏做嵌入 ...

发帖子,做贡献,攒积分,兑换。 我的积分已经够兑换试验箱了, 可是用不上。
姚总助力我们学习,直接送了。

lgnstar 发表于 2024-12-6 14:01:32

学习:jie:

大锤子 发表于 2024-12-7 22:18:30

<h1>试验箱例程21比较器做低压检测</h1>
<h2>实验功能</h2>
<p>如图所示,试验箱中P3.7 接可变电阻,通过改变电阻来改变P3.7的电压值,然后使用比较器跟内部1.19V电压做比较。<br />
如果通过P3.7输入的电压低于参考电压1.19V时将秒计数写入EEPROM,<br />
如果通过P3.7输入的电压高于参考电压1.19V时从EEPROM中读出原来记录的秒数继续显示<br />
数码管显示秒计数</p>
<h2>迁移思路</h2>
<p>1、通过滴答钩子每1ms向595写数码管显示数据;<br />
2、通过滴答钩子中的1秒改变秒计数值。 因为这里仅仅是记录秒数,不是RTC因此不需要使用软件RTC的功能;<br />
3、二值信号量通过比较器中断通知cmp任务用于将本地的秒数写入、读取EEPROM;</p>
<h2>效果展示</h2>
<video controls="controls" src="forum.php?mod=attachment&amp;aid=70117"></video>
<video controls="controls" src="forum.php?mod=attachment&amp;aid=70118"></video>
<h2>代码</h2>
<p><a href="forum.php?mod=attachment&amp;aid=70119" title="attachment"><img src="/source/plugin/zhanmishu_markdown/template/editor/images/upload.svg" alt="upload" /> 附件:cmp_eeprom.zip</a></p>

神农鼎 发表于 2024-12-8 00:40:55


大家多感受下官方强大的 【串口助手】 工具












CosyOS 发表于 2024-12-8 10:54:15

<p>推荐大家多多使用 STC-ISP 自带的 串口助手,定会感觉到它的强大!</p>

jun_1234 发表于 2024-12-11 16:47:03

CosyOS 发表于 2023-10-20 22:30
参会学习,【免费+包邮 送】:
【一箭双雕之USB转双串口,2个USB-CDC转串口+HID烧录】
【STC-USB Link1D,2 ...

祝愿STC越来越好
页: 90 91 92 93 94 95 96 97 98 99 [100] 101 102 103 104 105 106 107 108
查看完整版本: 全局不关总中断的 RTOS,CosyOS-III-V1.2.0, 送 擎天柱-AI8051U转89C52核心板