前言
最近一个项目需要实现433遥控器,用九齐的051D写了一个,分享出来加深下印象。
433遥控器,麻烦的是硬件电路,软件部分其实很简单,跟38K的遥控器没什么区别,都是给一个有效电平,然后433发送芯片通过板上的板载天线把433Mhz频率的信号发出。难在硬件设计这块,关于硬件用到的芯片是WF4455TD,是从别处照搬过来的电路,所以没什么可以分享的。
软件部分如下:
/* =========================================================================
* Project: 433遥控器
* File: main.c
* Description: 051D
*
*
* Author:
* Version: V1.0
* Date: 2022/5/7
=========================================================================*/
#include <ny8.h>
#include <ny8_romaccess.h>
#include "rom.h"
#include "ny8_constant.h"
#define u16 unsigned int
#define u8 unsigned char
void delay_us(int);
void delay_ms(int);
/* =======================================================================*/
#define KEY2 PORTBbits.PB5 //KEY2
#define KEY1 PORTBbits.PB4 //KEY1
#define KEY3 PORTBbits.PB2 //KEY3
#define KEY4 PORTBbits.PB0 //KEY4
#define REC PORTBbits.PB1 //REC 高电平有效
/* =======================================================================*/
u8 send_data=0;
u8 send_data_buf=0;
u8 i=0;
u8 f_bit_done=0; //发完1bit标志位
u8 f_stop=0; //发完一帧停止标志位
u8 t_stop=0; //停止时间
u8 f_send_low=0; //发1bit过程中 高低电平标志位
u8 t_send=0; //发送次数 即使一直按住按键 每次响应按键也只发送3帧数据
u8 f_send_end=0; //发下一帧包头标志位
u8 key_delay=0;
u8 f_onkey=0; //按住按键标志位
u8 t_onkey=0;
u8 no_key=0; //松手计时
u8 roll_code1=0;
u8 roll_code2=0;
u16 r_temp=0;
u16 r_temp1=0;
/* =======================================================================*/
void delay_us(int count) //@16M 2T 2.5us
{
for(;count>0;count--);
}
void delay_ms(int count) //@16M 2T
{
int i;
for(;count>0;count--)
{
for(i=0;i<=330;i++);
}
}
void sys_init(void)
{
PCON &= ~(1<<3); //关闭LVR 需要在IC_CONFIG里面设置寄存器配置
}
/* =======================================================================*/
void io_init(void)
{
IOSTB|=((1<<5)|(1<<4)|(1<<2)|(1<<0)); //B.0245输入
IOSTB&=~(1<<1); //B1 REC输出 空闲状态为常高电平
IOSTB&=~(1<<3); //B3输出 空闲口 置为输出
BPHCON&=~((1<<5)|(1<<4)|(1<<2)|(1<<0)); //开启B 0245口上拉电阻
KEY1=1;KEY2=1;KEY3=1;KEY4=1;REC=0;PB3=1;
}
void timer0_init(void)
{
T0MD &=~((1<<5)|(1<<3)); //FINST预分频给T0且为256分频
TMR0 = 50;
INTE |= (1<<0); //开启T0中断
PCON1 |= (1<<0); //开启T0
}
void timer1_init(void)
{
T1CR1=0X02; //当下溢发生,定时器 1 初始值从TMR1 寄存器被重新加载并继续下数
T1CR2=0X04; //32分频
TMR1 = 255;
INTE |=(1<<3); //开启T1中断
T1CR1 |=0x01; //开启T1
}
void pb_init(void)
{
BWUCON=0;
BWUCON|=((1<<5)|(1<<4)|(1<<2)|(1<<0));
INTE |=(1<<1); //开启PB中断
}
/* =======================================================================*/
void send_rec(void)
{
if(i>=24 && f_send_end==0) //总共发24位 + 1(下一帧包头)
{
TMR1=255;
REC=0;
i=0;
f_stop=1; //发完1帧 停12ms
send_data=0;
}
if(f_stop==0) //滚码从0000 0000开始以1为单位步进
{
if(i==0) //给滚码数据 0000 0000 从右往左发
{
send_data=roll_code1;
}
else if(i==8)
{
send_data=roll_code2; //给滚码数据 0000 0001 从右往左发
}
else if(i==16)
{
send_data=send_data_buf; //发各个键不同的键码
}
if(f_send_end==1) //是否发送下一帧包头
{
TMR1=48; //高电平时间为400us
REC = 1;
f_send_end=0;
}
else
{
if(send_data&0x01) //发“1”
{
if(f_send_low==0) //先发高电平
{
TMR1=52; //高电平时间443us
REC = 1;
f_send_low=1;
}
else
{
TMR1=145; //低电平时间1182us
REC = 0;
f_send_low=0;
f_bit_done=1;
}
}
else //发“0”
{
if(f_send_low==0) //先发高电平
{
TMR1=152; //高电平时间1242us
REC = 1;
f_send_low=1;
}
else
{
TMR1=45; //低电平时间385us
REC = 0;
f_send_low=0;
f_bit_done=1;
}
}
if(f_bit_done==1) //发完1bit数据
{
f_bit_done=0;
send_data=send_data>>1; //移位
i++; //计数
if(i==24)
{
f_send_end=1; //发完24bit数据 开始发下一帧包头
}
}
}
}
else
{
t_stop++; //两帧间隔时间 12ms
if(t_stop>5)
{
f_stop=0;
t_stop=0;
if(t_send>=1)
{
t_send--;
}
}
}
}
void key_scan(void)
{
if(KEY1==0 && KEY2==1 && KEY3==1 && KEY4==1 && f_onkey==0)
{
key_delay++;
if(key_delay>=5)
{
key_delay=0;
if(KEY1==0 && KEY2==1 && KEY3==1 && KEY4==1 && f_onkey==0)
{
f_onkey=1; //400ms后再次允许响应
no_key=0; //松手计时清零
t_onkey=0;
send_data_buf=0xBF; //赋值 1011 1111 收到的是 1111 1101
t_send=3; //发三次
i=0; //从第一bit数据开始发起
f_stop=0;
}
}
}
else if(KEY1==1 && KEY2==0 && KEY3==1 && KEY4==1 && f_onkey==0)
{
key_delay++;
if(key_delay>=5)
{
key_delay=0;
if(KEY1==1 && KEY2==0 && KEY3==1 && KEY4==1 && f_onkey==0)
{
f_onkey=1;
no_key=0;
t_onkey=0;
send_data_buf=0xEF; //赋值 1110 1111 收到的是 1111 0111
t_send=3;
i=0;
f_stop=0;
}
}
}
else if(KEY1==1 && KEY2==1 && KEY3==0 && KEY4==1 && f_onkey==0)
{
key_delay++;
if(key_delay>=5)
{
key_delay=0;
if(KEY1==1 && KEY2==1 && KEY3==0 && KEY4==1 && f_onkey==0)
{
f_onkey=1;
no_key=0;
t_onkey=0;
send_data_buf=0x8F; //赋值 1000 1111 收到的是 1111 0001
t_send=3;
i=0;
f_stop=0;
}
}
}
else if(KEY1==1 && KEY2==1 && KEY3==1 && KEY4==0 && f_onkey==0)
{
key_delay++;
if(key_delay>=5)
{
key_delay=0;
if(KEY1==1 && KEY2==1 && KEY3==1 && KEY4==0 && f_onkey==0)
{
f_onkey=1;
no_key=0;
t_onkey=0;
send_data_buf=0x7F; //赋值 0111 1111 收到的是 1111 1110
t_send=3;
i=0;
f_stop=0;
}
}
}
if(f_onkey==1)
{
if(KEY1==1 && KEY2==1 && KEY3==1 && KEY4==1)
{
no_key++;
if(no_key>=5)
{
no_key=0;
if(KEY1==1 && KEY2==1 && KEY3==1 && KEY4==1)
{
f_onkey=0;
t_onkey=0;
key_delay=0;
}
}
}
}
}
/* =======================================================================*/
void isr(void) __interrupt(0)
{
if(INTFbits.T1IF) //定时器1中断
{
INTFbits.T1IF=0;
if(t_send>=1)
{
send_rec();
}
}
if(INTFbits.T0IF)
{
INTFbits.T0IF=0;
TMR0 = 100;
key_scan();
}
if(INTFbits.PBIF) //仅作唤醒用
{
INTFbits.PBIF=0;
}
}
void main(void)
{
PCON &=~(1<<3); //关闭LVR
io_init();
delay_ms(50);
timer0_init();
timer1_init();
pb_init();
//获取滚码
r_temp = read_14bit_rom(&__rolling_code_addr);
r_temp1 = read_14bit_rom(&__rolling_code_addr+1);
roll_code1 = (u8)((r_temp&0xff00)>>8);
roll_code2 = (u8)r_temp&0x00ff; //低8位 0X00E的0-7位
INTF = 0; //清除所有中断标志
DISI(); //关闭总中断
ENI(); //开启总中断
while(1)
{
if(t_send<1 && KEY1==1 && KEY2==1 && KEY3==1 && KEY4==1)
{
delay_ms(200);
if(t_send<1 && KEY1==1 && KEY2==1 && KEY3==1 && KEY4==1)
{
REC=0;
SLEEP(); //睡眠
}
}
}
}
4个按键,4个不同的遥控码,按下按键后,连续发送3次同样的遥控码,每次间隔12ms。
这个项目是发24位数据,头码是一段高电平+低电平。具体协议怎么定可以自己规定。
比较特殊的一个地方就是,由于发送“1”或者“0”时,高电平时间很短并且“1”和“0”总周期一样,但是波形并不互补,所以定时器的初值要根据发不同的数据而改变。因为时间要求比较高,所以用的时定时器1,因为定时器1有自动重载功能。