STM8S单片机红外接收解码程序 带1602显示
2021-11-25 来源:eefocus
这几天在网上找了很多关于红外接收解码的程序,但都不是很理想。一般都是用延时来作为0和1的数据,或者注释不是很详细的,所以自己鼓捣了一个。
本程序是采用外部中断加定时器1来实现红外解码,STM8S单片机ABCD口都可作为外部中断,使用的遥控器为市面上大多数的。
需要的朋友们可以作为参考。
制作出来的实物图如下:
效果图
单片机源程序如下:
/***************可识别用户码 解码成功后显示在1602并LED闪烁一次*****************/
#include 'iostm8s208mb.h'//主控芯片的头文件
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
#define LED PI_ODR_ODR3
#define IR_IN PC_IDR_IDR1
#define LCD_EN PF_ODR_ODR4
#define LCD_RS PF_ODR_ODR0
#define LCD_DATA PB_ODR
//#define BUSY PB_ODR_ODR7
u16 LowTime,HighTime; //存储高低电平的宽度
u8 Counter_Time_H,Counter_Time_L;
u8 a[4]; //存放码值 分别为用户码 用户反码 数据码 数据反码
u8 tab[ ]= {'1602IR-CODE TEST'};
void delay_us(u16 n)
{
n<<=2;
while(--n);
}
void delay_ms(u16 t)
{
while(t--)
{
delay_us(1000);
}
}
void GPIO_Init(void)
{
EXTI_CR1|=0x20;//配置PC为仅下降沿触发
PI_DDR_DDR3=1;//LED
PI_CR1_C13=1;
PI_CR2_C23=1;
LED=1;
PC_DDR_DDR1=0;//IR_IN
PC_CR1_C11=1;
PC_CR2_C21=1;
PF_DDR_DDR4=1;//EN
PF_CR1_C14=1;
PF_CR2_C24=1;
PF_DDR_DDR0=1;//RS
PF_CR1_C10=1;
PF_CR2_C20=1;
PB_DDR=0xff;//DATA
PB_CR1=0xff;
PB_CR2=0xff;
}
void Write_Com(u8 com)
{
LCD_RS=0;
LCD_DATA=com;
delay_ms(5);
LCD_EN=1;
delay_ms(5);
LCD_EN=0;
}
void Write_Data(u8 data)
{
LCD_RS=1;
LCD_DATA=data;
delay_ms(5);
LCD_EN=1;
delay_ms(5);
LCD_EN=0;
}
void LCD_Init(void)
{
LCD_EN=0;
Write_Com(0x38);
Write_Com(0x0c);
Write_Com(0x06);
Write_Com(0x01);
}
void TIM1_Init(void)
{
TIM1_CR1=0x00; //close timer1
TIM1_IER = 0x01; //允许更新中断
TIM1_PSCRH=0x00; //16Mhz/16=1us,16分频
TIM1_PSCRL=0x0f;
// TIM1_CNTRH=0x00;
// TIM1_CNTRL=0x00;
TIM1_ARRH=0xff; //自动装载最大值
TIM1_ARRL=0xff;
}
void Clock_Init(void)
{
CLK_CKDIVR=0x00; //16M
}
void LED_ACT(void) //延时时间太大会影响灵敏度
{
LED=0;
delay_ms(10);
LED=1;
delay_ms(10);
}
u8 DeCode(void)
{
u8 i,j;
u8 temp; //暂存变量
for(i=0;i<4;i++) //
{
for(j=0;j<8;j++) //
{
temp=temp>>1; //
TIM1_CNTRH=0;
TIM1_CNTRL=0;
TIM1_CR1|=0x01;
while(IR_IN==0); //先判断是否为0
TIM1_CR1=0x00;
Counter_Time_H=TIM1_CNTRH;
Counter_Time_L=TIM1_CNTRL;
LowTime=Counter_Time_H*256+Counter_Time_L; //
TIM1_CNTRH=0;
TIM1_CNTRL=0;
TIM1_CR1|=0x01;
while(IR_IN==1); //再判断是否为1
TIM1_CR1=0x00;
Counter_Time_H=TIM1_CNTRH;
Counter_Time_L=TIM1_CNTRL;
HighTime=Counter_Time_H*256+Counter_Time_L;
if((LowTime<420)||(LowTime>690))
return 0; //太大或太小舍去
if((HighTime>460)&&(HighTime<660))
temp=temp&0x7f; //'0' 560us+-100
if((HighTime>1480)&&(HighTime<1880))
temp=temp|0x80; //'1' 1680us+-500
}
a[i]=temp;
}
// if(a[2]==~a[3])
return 1;
}
void two_2_bcd(u8 data) //将二进制码转换为BCD码
{
u8 temp; //暂存
temp=data;
data&=0xf0;
data>>=4;
data&=0x0f;
if(data<=0x09)
{
Write_Data(0x30+data); //显示0-9
}
else
{
data=data-0x09;
Write_Data(0x40+data); //显示A-F
}
data=temp;
data&=0x0f;
if(data<=0x09)
{
Write_Data(0x30+data);
}
else
{
data=data-0x09;
Write_Data(0x40+data);
}
Write_Data(0x48); //显示“H”
}
void Disp_1(void) //显示第二行:码值
{
Write_Com(0x80+0x40);
two_2_bcd(a[0]);
Write_Data(0x20); //空格
two_2_bcd(a[1]);
Write_Data(0x20); //空格
two_2_bcd(a[2]);
Write_Data(0x20); //空格
two_2_bcd(a[3]);
}
void Disp_2(void) //显示第一行:固定字符
{
u8 num; //
Write_Com(0x80);
for(num=0;num<16;num++)
{
Write_Data(tab[num]);
delay_ms(5);
}
}
void CHECK_User(void)
{
// if((a[0]==0x00)&&(a[1]==0xff)) //判别用户码及反码
// {
LED_ACT();
// }
}
void main(void)
{
asm('sim');//MAIN程序的优先级配置为3级(关总中断)
GPIO_Init();
Clock_Init();
TIM1_Init();
LCD_Init();
// delay_ms(10);
Write_Com(0x01); //清屏
Disp_2();
asm('rim');//MAIN程序的优先级由3级降低至0级(开总中断)
while(1);//死循环
}
#pragma vector=0x07
__interrupt void EXTI_PORTC_IRQHandler(void)
{
PC_CR2_C21=0;//禁止PC0端口外部中断
TIM1_CNTRH=0;
TIM1_CNTRL=0;
TIM1_CR1=0x01; //open timer1
while(IR_IN==0);
TIM1_CR1=0x00; //
Counter_Time_H=TIM1_CNTRH;
Counter_Time_L=TIM1_CNTRL;
LowTime=Counter_Time_H*256+Counter_Time_L;
TIM1_CNTRH=0; //
TIM1_CNTRL=0; //
TIM1_CR1=0x01; //
while(IR_IN==1); //
TIM1_CR1=0x00; //
Counter_Time_H=TIM1_CNTRH;
Counter_Time_L=TIM1_CNTRL;
HighTime=Counter_Time_H*256+Counter_Time_L;
if((LowTime>8500)&&(LowTime<9500)&&(HighTime>4000)&&(HighTime<5000)) //引导码9000us+-500 4500us+-500
{
if(DeCode()==1)
{
Disp_1();
CHECK_User();
}
}
PC_CR2_C21=1;//使能PC0端口外部中断
}
#pragma vector=0x0D
__interrupt void TIM1_UPD_OVF_TRG_BRK_IRQHandler(void)
{
TIM1_SR1&=0xfe;//清除溢出中断标志位'UIF'
}
- STM8S 使用IAR在线调试配置
- IAR FOR STM8S 错误 An error occurred while retrieving GDI features: gdi-error [40201]解决方法
- STM8S定时器操作
- IAR调试STM8S遇到函数返回值错误的问题
- STM8S 定时器第一次使用时间不准确的问题
- 解决stm8s配置timer2中断时间不准
- STM8S被设定读保护的芯片如何解除读保护,重新下载程序
- stm8 stm8s stm8af 485接口 modbus协议代码
- STM8S学习笔记之三(STM8 SysClk)
- 下一代汽车微控制器:意法半导体技术解析