在杰理的AC7916N实现了433射频的数据发送,在杰理的AD15系列实现433射频接收,本代码用于门铃项目收发,下面请看代码。
首先是AC7916N的433数据发送代码,发送部分的程序放在一个400us的定时器中断服务程序中,这种方式笔者并不推荐,由于笔者本人较懒,能跑的程序就不想动,后期读者可以通过信号量或事件的方式,对其进行完善,代码只供读者参考。
send_data_433.c:
#include "send_data_433.h"
#include "wifi/wifi_connect.h"
#include "timer4.h"
#include "pc_cmd_analysis.h"
/******************************* 433Data ****************************************/
static char us_num = 0;
static char bit_num = 0;
u8 dat_433=0;
u8 SendData_433[4]={0};
u8 Send433Data[4]={0};
u8 flag_send_data = 0;
u8 send_num = 0;
u8 Cnt_SendAndLead = 0;
u8 Cnt_SendAndLead_More = 0;
#define MLOGD printf
static void send_pin_init()
{
//设置引脚的方向为输出,并设置为低电平
gpio_direction_output(PIN_DATA, 0);
}
static void set_pin_high()
{
gpio_direction_output(PIN_DATA, 1);
}
static void set_pin_low()
{
gpio_direction_output(PIN_DATA, 0);
}
void HI_433GetAddress(void)
{
//void *cfg_handle = wifi_cfg_init();
unsigned char mac_addr[6] = {0};
wifi_get_mac(mac_addr);
SendData_433[0]=mac_addr[2];
SendData_433[1]=mac_addr[3];
SendData_433[2]=mac_addr[4];
SendData_433[3]=mac_addr[5];
/*SendData_433[0]=0xf8;
SendData_433[1]=0x1b;
SendData_433[2]=0x31;
SendData_433[3]=0xac;*/
#ifdef MCU_DEBUG_PRINT
printf("WIFI_MAC:=%02X:%02X:%02X:%02X:%02X:%02X\n",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
printf("WIFI_433data:=%02X:%02X:%02X:%02X\n",
SendData_433[0], SendData_433[1], SendData_433[2], SendData_433[3]);
#endif
}
void Lead_Code433() //引导码+同步码:高电平延时400us+低电平延时12.4ms
{
if (us_num < 1)
set_pin_high();
else
set_pin_low();
us_num++;
if (us_num >= 32)
{
us_num = 0;
Cnt_SendAndLead++;
return;
}
}
void Send_Data_433(unsigned int dat)
{
if(us_num == 0)
dat_433 = dat;
bit_num++;
us_num++;
if (dat_433 & 0x80) // dat_433第8位为1
{
if (bit_num < 4)
set_pin_high();
else if (bit_num == 4)
set_pin_low();
}
else
{
if (bit_num == 1)
set_pin_high();
else if (bit_num > 1)
set_pin_low();
}
if (bit_num == 4)
{
dat_433 = dat_433 << 1; //左移先发位
// printf("DATA=0x%x bit_num =%d,us_num=%d\n",dat_433,bit_num,us_num);
bit_num = 0;
}
if (us_num >= 32)
{
us_num=0;
bit_num = 0;
Cnt_SendAndLead++;
if (Cnt_SendAndLead > 4)
{
Cnt_SendAndLead = 0;
Cnt_SendAndLead_More++;
if (Cnt_SendAndLead_More >= (10 * send_num)) // 20次
{
Cnt_SendAndLead_More = 0;
if(!Send_433_Test_flag)//产测时是不停发送433数据的,
flag_send_data = 0;//定时中断停止发送
}
}
return;
}
}
void HI_SendData_433_1527(unsigned char Address0,unsigned char Address1,unsigned char Address2,unsigned char Address3)
{
switch(Cnt_SendAndLead)
{
case 0:
Lead_Code433(); //Lead_Code1527();
break;
case 1:
Send_Data_433(Address0); //Send_Data1527(Address0);
break;
case 2:
Send_Data_433(Address1); //Send_Data1527(Address1);
break;
case 3:
Send_Data_433(Address2); //Send_Data1527(Address2);
break;
case 4:
Send_Data_433(Address3); //Send_Data1527(Address3);
break;
}
#ifdef MCU_DEBUG_PRINT
//printf("Send 433Data is OK\n\r");
#endif
}
void Senddata_433_task(int num)
{
u8 i=0;
Send433Data[0] = (SendData_433[0]& 0x0F) | (0x10);//SendData_433是wifi_cfg_get_addr1(cfg_handle, (char *)mac_addr);来的
Send433Data[1] = SendData_433[1];
Send433Data[2] = SendData_433[2];
Send433Data[3] = SendData_433[3];
for(i=0;i<4;i++)
MLOGD("Send433Data[%d]=0x%x | SendData_433[%d]=0x%x",i,Send433Data[i],i,SendData_433[i]);
MLOGD("\n");
set_pin_low();
flag_send_data = 1;
send_num = num;
TMR->CNT = 0;
/*
for(i=0;i<num;i++)
{
HI_SendData_433_1527(Send433Data[0],Send433Data[1],Send433Data[2],Send433Data[3]);
}*/
}
/*
int factory_flag;
void Senddata_433_test_start(void *args)//用于产测
{
static u8 cnt;
unsigned int Send433Data[4]={0};
MLOGD("Senddata_433_test_start \n");
Send433Data[0] = (SendData_433[0]& 0x0F) | (0x10);
Send433Data[1] = SendData_433[1];
Send433Data[2] = SendData_433[2];
Send433Data[3] = SendData_433[3];
factory_flag = 0;
while(factory_flag == 0)
{
HI_SendData_433_1527(Send433Data[0],Send433Data[1],Send433Data[2],Send433Data[3]);
os_time_dly(100);//一个数10ms,100个就是延时1000ms
if(++cnt >1)
{
factory_flag = 1;
cnt =0;
}
}
MLOGD("Senddata_433_test_start is ok\n");
//OS_TaskDelete(NULL);
}
u8 Senddata_433_test_end(void)
{
factory_flag =1;
MLOGD("Senddata_433_test_end \n");
return 1;
}
*/
void HI_Send433_task(void *args)
{
int err;
int msg[32]; //接收消息队列buf
#ifdef MCU_DEBUG_PRINT
printf("HI_Send433_task is runnig \n\r");
#endif
while(1)
{
printf("HI_Send433_task\n");
//阻塞等待消息
err = os_taskq_pend("taskq", msg, ARRAY_SIZE(msg));//在os_taskq_pend中msg[0]接收的是消息个数,即argc==msg[0],argv[0]==msg[1]
if (err != OS_TASKQ || msg[0] != Q_USER) {
printf("os_taskq_pend err!");
continue;
}
MLOGD("HSend433 Reci!\n");
switch (msg[1]) {
case MESSAGE_433:
printf("get MESSAGE_1, data : %d\n", msg[2]);
MLOGD("HSend433 Data---------! \n\r");
Senddata_433_task(2);//50zhen
break;
}
}
}
void send_message_433(u8 messages)
{
int err;
int argc = 2; //消息个数
int argv[4];
//发送的消息内容
argv[0] = messages;//在os_taskq_pend中msg[0]接收的是消息个数,即argc==msg[0],argv[0]==msg[1]
argv[1] = 12;
_retry1:
err = os_taskq_post_type("send_433_data_task", Q_USER, argc, argv);
//err = os_taskq_post("queue_task", argc, argv[0], argv[1]);//采用该接口发送信息时可变参数个数不能超过8个
if(err == OS_Q_FULL)
{
os_time_dly(5);
printf("err == OS_Q_FULL\n");
goto _retry1;
}
printf("MESSAGE_433 send succ\n");
}
/*在任务列表中添加:
{"send_433_data_task", 23, 512, 64 },
*/
void send_data_433_entrance(void)
{
static int send433data_pid;
send_pin_init();
//sys_timer_add(NULL, Rf433Send_Handle,10000);//300MS
thread_fork("send_433_data_task", 31, 1024, 128, &send433data_pid, HI_Send433_task, NULL);
}
late_initcall(send_data_433_entrance);
send_data_433.h:
#ifndef _SEND_DATA_433_H
#define _SEND_DATA_433_H
#include "app_config.h"
#include "asm/includes.h"
#include "generic/typedef.h"
#include "asm/clock.h"
#include "asm/adc_api.h"
#include "system/timer.h"
#include "asm/efuse.h"
#include "asm/p33.h"
#include "asm/power_interface.h"
#include "device/gpio.h"
#include "system/includes.h"
#include "sys_timer.h"
#define PIN_DATA IO_PORTC_01
extern u8 Send433Data[4];
extern u8 flag_send_data;
void HI_433GetAddress(void);
void Senddata_433_test_start(void *args);
void Senddata_433_task(int num);
void HI_SendData_433_1527(unsigned char Address0,unsigned char Address1,unsigned char Address2,unsigned char Address3);
void send_message_433(u8 messages);
enum {
MESSAGE_433 = 0x01,
};
#endif
timer5.c:
#include "timer5.h"
#include "send_data_433.h"
//用户只能选择:JL_TIMER2、JL_TIMER3、JL_TIMER4、JL_TIMER5
//PWM使用定时器2或者3映射PWM时候,不能用于定时
#define USE_TIMER_TEST1_DEMO
#ifdef USE_TIMER_TEST1_DEMO
JL_TIMER_TypeDef *TMR = JL_TIMER5;//选择定时器5
static u8 timer_irq = IRQ_TIMER5_IDX;//选择定时器4
static const u8 timer_index[16] = {0, 4, 1, 5, 2, 6, 3, 7, 8, 12, 9, 13, 10, 14, 11, 15};
static const u32 timer_table[16] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
static u32 timer_clk = 0;
#define AWINLINE __attribute__((always_inline))
//#define TSEC SEC_USED(.volatile_ram_code) //当中断1ms一下,建议使用函数放在内部ram
#define TSEC
static AWINLINE TSEC void timer_cfg(u32 freq, u32 us)
{
u32 clock = timer_clk;
u8 psc = 0;
u8 tmp = 0;
u32 prd = 0;
u32 ts = us / (1000 * 1000);//计算秒
u32 tu = us % (1000 * 1000);//计算秒剩余us
u8 i;
float tp = 0;
if (freq >= clock) {
freq = clock;
} else if (freq <= 1) {
freq = 1;
if (ts) {
tp = (float)tu / (1000 * 1000);
}
}
/*求prd值*/
prd = clock / freq;
if (prd > 65535) {
for (psc = 0; psc < 16; psc++) {
prd = (u32)(clock / (timer_table[psc]) / freq);
if (prd <= 65535) {
break;
} else if (psc == 15) {
prd = 65535;
break;
}
}
}
prd = ts ? (prd * ts + tp * prd) : prd;
psc = timer_index[psc];
TMR->CON = 0;
TMR->CNT = 0;
TMR->CON |= BIT(14);
TMR->PRD = prd;
TMR->CON |= psc << 4; //lsb_clk分频
TMR->CON |= BIT(0);
}
static void TSEC timer_set(u32 us)//设置时间,该函数可以在中断调用重新设置定时器值
{
u32 freq = 1000000 / us;
timer_cfg(freq, us);
}
static void TSEC timer_freq_set(u32 freq)//设置频率,该函数可以在中断调用重新设置定时器值
{
timer_cfg(freq, 0);
}
static ___interrupt TSEC void timer_isr(void)//中断
{
if (TMR->CON & BIT(15)) {
TMR->CON |= BIT(14);
//putchar('@');
//todo,中断函数执行程序...
if(flag_send_data)
{
HI_SendData_433_1527(Send433Data[0],Send433Data[1],Send433Data[2],Send433Data[3]);
}
}
}
//example test
static int timer_entrance(void)
{
timer_clk = clk_get("timer");//先获取定时器的时钟源
request_irq(timer_irq, 7, timer_isr, 0);//注册中断函数定和中断优先级
#if 1
timer_set(400); //初始化400us进一次中断
#else
//timer_freq_set(10000);//设置10K频率进中断
#endif
return 0;
}
late_initcall(timer_entrance);
#endif
timer5.h
#ifndef _TIMER5_H
#define _TIMER5_H
#include "app_config.h"
#include "system/includes.h"
#include "device/device.h"
#include "asm/clock.h"
extern JL_TIMER_TypeDef *TMR;
#endif
接下来的部分是在AD15N系列实现的433接收部分,其处理程序是放在定时器80us中断里面处理的,笔者这样写的代码可以跑,但是不保证没有问题,所以读者并不推荐这种方式,读者可以尝试用标志位的方式。好了,就说到这里,下面请看接收端的代码:
receive_433.c:
#include "receive_433.h"
#include "key.h"
#define LOG_TAG_CONST NORM
#define LOG_TAG "[normal]"
#include "debug.h"
#include "msg.h"
#include "vm.h"
#define printf log_info
unsigned int Rf_Cnt;
unsigned int Lo_Cnt;
unsigned int Hi_Cnt;
unsigned int Count_Lead;
unsigned int Count_Data_Hi;
unsigned int Count_Data_Lo;
unsigned int Recv_Bit_Cnt;
unsigned int Recv_Byte_Cnt;
unsigned char Recv_Data_Buf;
unsigned char Rf_Data[4];
unsigned int Rf_Control_Data;
unsigned char Rf_Address[4] ={0};
u8 NSong,NVolume;
u8 Timer2 =0;
u8 jk=0;
u8 Mute_flag = 0;
u8 PLAY_FLAG = 0;
u8 P13_LOCK = 0;
u8 Addr_FLAG = 0; //Press and hold to update the address only once
u8 TIMER2_FLAG = 0;
u8 WDT_TIME =0;
u8 mutenum =0;
extern void delay(volatile u32 t);
void HI_EraseAddress(void)//往flash中写0xff 清除配对
{
Rf_Address[0] = 0xFF;
Rf_Address[1] = 0xFF;
Rf_Address[2] = 0xFF;
Rf_Address[3] = 0xFF;
vm_write(VM_INDEX_433_ADDR, Rf_Address, sizeof(Rf_Address));
}
void timer0_handle(void)
{
switch(Rf_Cnt)
{
case 0 :
//printf("Rf_Cnt = %d\n",Rf_Cnt); //12ms引导码
if(!(DATA_433)) //低电平累积次数
{
//printf("DATA_433==0\n",Rf_Cnt);
Count_Lead++;
}
else //高电平判断范围
{
//printf("DATA_433==1\n",Rf_Cnt);
if((Count_Lead >= 70) && (Count_Lead <= 200)) //5.6ms - 16ms
{
Count_Lead=0;
Recv_Data_Buf = 0x00; //初始化参数
Count_Data_Hi = 0;
Count_Data_Lo = 0;
Recv_Bit_Cnt = 0;
Recv_Byte_Cnt = 0;
Rf_Cnt=1;
}
else //范围不对退出
{
Count_Lead=0;
Rf_Cnt=0;
}
}
break;
case 1 :
//printf("Rf_Cnt = %d\n",Rf_Cnt); //数据位高电平部分判断
if(DATA_433) //高电平累积次数
{
//printf("DATA_433 == 1\n");
Count_Data_Hi++;
}
else //低电平判断范围
{
if((Count_Data_Hi >= 1) && (Count_Data_Hi <= 30)) // 80us - 2.4ms
{
Hi_Cnt = Count_Data_Hi; //存储计数,区分0跟1数据用的
Count_Data_Hi = 0;
Rf_Cnt=2;
//printf("Rf_Cnt ==2 \n");
}
else
{
Rf_Cnt=0;
//printf("Rf_Cnt ==0 \n");
}
}
break;
case 2:
//printf("Rf_Cnt = %d\n",Rf_Cnt);
//数据位低电平部分判断
if(DATA_433==0) //低电平累积次数
{
Count_Data_Lo++;
}
else //高电平判断范围
{
if((Count_Data_Lo >= 1) && (Count_Data_Lo <= 30)) // 80us - 2.4ms
{
Lo_Cnt = Count_Data_Lo; //存储计数,区分0跟1数据用的
Count_Data_Lo = 0;
Rf_Cnt=3;
}
else
{
Rf_Cnt=0;
}
}
break;
case 3 :
//printf("Rf_Cnt = %d\n",Rf_Cnt);
Recv_Data_Buf <<= 1; //数据移位
if(Hi_Cnt>Lo_Cnt) //0跟1的区分,判断高低电平哪个长
{
Recv_Data_Buf|=0x01;
}
else
{
Recv_Data_Buf&=0xFE;
}
Recv_Bit_Cnt ++;
if(Recv_Bit_Cnt>7) //每8bit整理出一个byte
{
Rf_Data[Recv_Byte_Cnt]=Recv_Data_Buf; //存到数组里面
Recv_Bit_Cnt = 0;
Recv_Byte_Cnt++;
Recv_Data_Buf = 0x00;
}
if(Recv_Byte_Cnt>3) //整理出三个byte
{
Rf_Control_Data=Rf_Data[0]&0xF0; //提取4bit控制数据
Rf_Cnt = 4; //进入到功能判断
if(LOGE) printf("Rf_Data[0]%x Rf_Data[1]%x Rf_Data[2]%x Rf_Data[3]%x Rf_Control_Data=0x%x MUTE_LONG=%bd\n\r",Rf_Data[0],Rf_Data[1],Rf_Data[2],Rf_Data[3],Rf_Control_Data,MUTE_LONG);
//if(LOGE) printf("Rf_Data[0]%bd Rf_Data[1]%bd Rf_Data[2]%bd Rf_Control_Data is %bd\n\r",Rf_Data[0],Rf_Data[1],Rf_Data[2],Rf_Control_Data);
}
else
{
Rf_Cnt = 1; //不够3byte,继续去解码数据
}
break;
case 4 : //功能判断
printf("Rf_Cnt = %d\n",Rf_Cnt);
switch(Rf_Control_Data)
{
case 0x10 :
if(LOGE) printf("[0]:address%x data:%x | [1]:Address:%x data:%x | [2]:Address:%x data:%x | [3]:Address:%x data:%x \n\r",Rf_Address[0],Rf_Data[0],Rf_Address[1],Rf_Data[1],Rf_Address[2],Rf_Data[2],Rf_Address[3],Rf_Data[3]);
if(MUTE_LONG >2)
{
if(Addr_FLAG ==0)
{
P13_LOCK = 1;
Rf_Address[0] = Rf_Data[0]&0x0F;
Rf_Address[1] = Rf_Data[1];
Rf_Address[2] = Rf_Data[2];
Rf_Address[3] = Rf_Data[3];
Addr_FLAG = 1;
if(LOGE) printf("Rf_Address[0]:0x%x Rf_Address[1]:0x%x Rf_Address[2]:0x%x Rf_Address[3]:0x%x Rf_Control_Data is %d\n\r",Rf_Address[0],Rf_Address[1],Rf_Address[2],Rf_Address[3],Rf_Control_Data);
//KEYDOWM_SongChoose(0x1A);
//HI_EraseAddress();
//HI_SetAddress(Rf_Address[0],Rf_Address[1],Rf_Address[2],Rf_Address[3]);
//HI_WDT_WatchDogFeed();//喂狗
vm_write(VM_INDEX_433_ADDR, Rf_Address, sizeof(Rf_Address));
post_msg(1, MSG_PLAY_FILE1);
delay(1000);
P13_LOCK = 0;
}
break;
}
if(((Rf_Data[0] &0x0F) == Rf_Address[0]) && (Rf_Data[1] == Rf_Address[1]) && (Rf_Data[2] == Rf_Address[2])&& (Rf_Data[3] == Rf_Address[3]))
{
if(LOGE) printf("Receive data AA and play mucis %bx\n\r",Rf_Control_Data);
//if((PLAY_FLAG ==0)&&(mutenum ==0))
//{
//PLAY_FLAG = 1;
//KEYDOWM_SongChoose(NSong);
//KEYDOWM_VolumeChoose(NVolume);
post_msg(1, MSG_PLAY_FILE1);
post_msg(1, MSG_SET_PLAY_FLAG);//播放四次标志位置1
delay(100);
//APK_HeadSEND();
//APK_CyclePlayMusic();
Timer2 =1;
//if(TIMER2_FLAG < 1) set_TR2;
TIMER2_FLAG++;
if(LOGE) printf("11111111111111111\n\r");
//while(PLAY_FLAG);
if(LOGE) printf("22222222222222222221\n\r");
//}
break;
}
/* case 0xA0 :
if(P13_LONG >0)
{
Rf_Address[0] = Rf_Data[0]&0x0F;
Rf_Address[1] = Rf_Data[1];
Rf_Address[2] = Rf_Data[2];
if(LOGE) printf("Rf_Address[0]:0x%x Rf_Address[1]:0x%x Rf_Address[2]:0x%x Rf_Control_Data is %d\n\r",Rf_Address[0],Rf_Address[1],Rf_Address[2],Rf_Control_Data);
KEYDOWM_SongChoose(0x15);
}*/
default:
break;
}
Rf_Cnt = 0; //做完操作状态回零
break;
default:
Rf_Cnt = 0;
break;
}
}
receive_433.h:
#ifndef _RECEIVE_433_H
#define _RECEIVE_433_H
#include "gpio.h"
#define LOGE 1
#define DATA_433 (JL_PORTA->IN & BIT(1))
#define PIN_433_INIT() do{\
JL_PORTA->PU |= BIT(1),/*开启上拉*/\
JL_PORTA->PD &= ~BIT(1),/*关闭下拉*/\
JL_PORTA->DIE |= BIT(1),/*输入允许*/\
JL_PORTA->DIR |= BIT(1);/*设为输入*/\
}while(0)
extern void timer0_handle(void);
extern u8 Addr_FLAG;
extern unsigned char Rf_Address[4];
extern void HI_EraseAddress(void);
#endif
至此,代码结束,写得很烂,请谅解。