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&aid=70117"></video>
<video controls="controls" src="forum.php?mod=attachment&aid=70118"></video>
<h2>代码</h2>
<p><a href="forum.php?mod=attachment&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越来越好