460 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			460 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "24l01.h"
 | ||
| #include "nrf.h"
 | ||
| #include "stdio.h"
 | ||
| #include "buff.h"
 | ||
| #include "string.h"
 | ||
| #include "rthw.h"
 | ||
| 
 | ||
| 
 | ||
| // 接口函数
 | ||
| static void nrf_dalay_us(int us)
 | ||
| {
 | ||
|     rt_hw_us_delay(us);
 | ||
| }
 | ||
| 
 | ||
| static int nrf_get_random(void)
 | ||
| {
 | ||
|     static int d=0;
 | ||
|     d++;
 | ||
|     return d;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /* -------------------------- 通信协议相关 ---------------------------- */
 | ||
| 
 | ||
| 
 | ||
| typedef struct{
 | ||
|     
 | ||
|     // 连接状态
 | ||
|     int connect_state;
 | ||
|     
 | ||
|     // 数据交互状态
 | ||
|     int interaction_err;
 | ||
|     
 | ||
|     // 不发送回应
 | ||
|     int no_respond;
 | ||
|     
 | ||
|     // 数据发送成功
 | ||
|     int send_ok;
 | ||
|     
 | ||
|     // 交互超时时间,us
 | ||
|     int interaction_time_out;
 | ||
|     
 | ||
|     // 连接超时时间,ms
 | ||
|     int connect_time_out;
 | ||
|     
 | ||
|     // 重试次数
 | ||
|     int retry_itmes;
 | ||
|     
 | ||
|     // 信道频率
 | ||
|     int channel_frequency;
 | ||
|     
 | ||
|     // 发送数据包总数
 | ||
|     int send_packet_all;
 | ||
|     
 | ||
|     // 发送失败的数据包总数
 | ||
|     int send_packet_failed;
 | ||
|     
 | ||
|     // 本机地址
 | ||
|     u8 addr_myself[5];
 | ||
|     
 | ||
|     // 目标机地址
 | ||
|     u8 addr_dst[5];
 | ||
|     
 | ||
|     // 最近发送使用的魔数
 | ||
|     u8 magic_number_send;
 | ||
|     
 | ||
|     // 最近接收使用的魔数
 | ||
|     u8 magic_number_recv;
 | ||
|     
 | ||
| }nrf_env_struct;
 | ||
| 
 | ||
| static nrf_env_struct g_nrf_env={0};
 | ||
| static data_buff g_buff={0};
 | ||
| static const u8 g_dst_addr[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //发送地址
 | ||
| static const u8 g_my_addr[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //发送地址
 | ||
| 
 | ||
| 
 | ||
| // 设置连接状态
 | ||
| int nrf_set_connect_state(int s)
 | ||
| {
 | ||
|     g_nrf_env.connect_state=s;
 | ||
|     return NRF_OK;
 | ||
| }
 | ||
| 
 | ||
| // 获取连接状态
 | ||
| int nrf_get_connect_state(void)
 | ||
| {
 | ||
|     return g_nrf_env.connect_state;
 | ||
| }
 | ||
| 
 | ||
| // 设置通信地址
 | ||
| int nrf_set_addr(const u8 *my,const u8 *dst)
 | ||
| {
 | ||
|     if(my) memcpy(g_nrf_env.addr_myself,my,5);
 | ||
|     if(dst) memcpy(g_nrf_env.addr_dst,dst,5);
 | ||
|     nrf24l01_set_addr(g_nrf_env.addr_myself,g_nrf_env.addr_dst);
 | ||
|     return NRF_OK;
 | ||
| }
 | ||
| 
 | ||
| // 设置重试次数
 | ||
| int nrf_set_retry_times(int times)
 | ||
| {
 | ||
|     g_nrf_env.retry_itmes=times;
 | ||
|     return NRF_OK;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // 设置信道
 | ||
| int nrf_set_chan(u8 chan)
 | ||
| {
 | ||
|     if(chan>=64) return NRF_ERR;
 | ||
|     if(g_nrf_env.channel_frequency!=chan)
 | ||
|     {
 | ||
|         g_nrf_env.channel_frequency=chan;
 | ||
|         nrf24l01_set_chan(g_nrf_env.channel_frequency);
 | ||
|     }
 | ||
|     return NRF_OK;
 | ||
| }
 | ||
| 
 | ||
| // 获取当前信道
 | ||
| int nrf_get_chan(void)
 | ||
| {
 | ||
|     return g_nrf_env.channel_frequency;
 | ||
| }
 | ||
| 
 | ||
| // 设置超时时间
 | ||
| int nrf_set_time_out(int connect_time_ms,int interaction_time_us)
 | ||
| {
 | ||
|     g_nrf_env.connect_time_out=connect_time_ms;
 | ||
|     g_nrf_env.interaction_time_out=interaction_time_us;
 | ||
|     return 0;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // 获取发送数据包情况
 | ||
| int nrf_get_packet_num(int *all,int *failed)
 | ||
| {
 | ||
|     if(all) *all=g_nrf_env.send_packet_all;
 | ||
|     if(failed) *failed=g_nrf_env.send_packet_failed;
 | ||
|     return NRF_OK;
 | ||
| }
 | ||
| 
 | ||
| // 清空数据包发送记录
 | ||
| int nrf_clear_packet_num(void)
 | ||
| {
 | ||
|     g_nrf_env.send_packet_all=0;
 | ||
|     g_nrf_env.send_packet_failed=0;
 | ||
|     return NRF_OK;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // 发送完成数据回调
 | ||
| void nrf_send_cb(void *t);
 | ||
| 
 | ||
| // 接收到数据回调
 | ||
| void nrf_recv_cb(void *t);
 | ||
| 
 | ||
| 
 | ||
| // 无线通信初始化
 | ||
| int nrf_init(void)
 | ||
| {
 | ||
|     memset(&g_nrf_env,0,sizeof(nrf_env_struct));
 | ||
|     
 | ||
|     buff_init(&g_buff,4096*16,0,0,0);
 | ||
|     
 | ||
|     nrf24l01_set_recv_cb(nrf_recv_cb,0);
 | ||
|     nrf24l01_set_send_cb(nrf_send_cb,0);
 | ||
|     
 | ||
|     nrf24l01_init();
 | ||
|     g_nrf_env.channel_frequency=-1;
 | ||
|     nrf_set_connect_state(1);
 | ||
|     nrf_set_addr(g_my_addr,g_dst_addr);
 | ||
|     nrf_set_chan(20);
 | ||
|     nrf_set_time_out(1000,5000);
 | ||
|     nrf_set_retry_times(1000);
 | ||
|     
 | ||
|     if(nrf24l01_check()==0)
 | ||
|         return NRF_OK;
 | ||
|     else 
 | ||
|     {
 | ||
|         buff_deinit(&g_buff);
 | ||
|         return NRF_ERR;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| // 去初始化
 | ||
| int nrf_deinit(void)
 | ||
| {
 | ||
|     buff_deinit(&g_buff);
 | ||
|     nrf24l01_deinit();
 | ||
|     return NRF_OK;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| // 读取一个字节数据,NRF_OK成功
 | ||
| int nrf_read_byte(uint8_t *data)
 | ||
| {
 | ||
|     if(buff_read_byte(&g_buff,data)==0)
 | ||
|         return NRF_OK;
 | ||
|     else return NRF_ERR;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // 清空接收区
 | ||
| int nrf_clear(void)
 | ||
| {
 | ||
|     buff_clear(&g_buff);
 | ||
|     return NRF_OK;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // 发送任意长度的数据,成功返回NRF_OK
 | ||
| int nrf_send(void *data,int size,int *rs)
 | ||
| {
 | ||
|     int ret=NRF_OK;
 | ||
|     int len=0;
 | ||
|     uint8_t *ptr=data;
 | ||
|     nrf_load_struct load;
 | ||
|     while(size>0)
 | ||
|     {
 | ||
|         if(size>29)
 | ||
|             len=29;
 | ||
|         else len=size;
 | ||
|         nrf_packet_pack(&load,NRF_TYPE_DATA,ptr,len);
 | ||
|         if(ret=nrf_send_load(&load),ret!=NRF_OK)
 | ||
|         {
 | ||
|             return ret;
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|             if(rs) (*rs)+=len;
 | ||
|             size-=len;
 | ||
|             ptr+=len;
 | ||
|         }
 | ||
|     }
 | ||
|     return ret;
 | ||
| }
 | ||
| 
 | ||
| // 同步通信信道
 | ||
| int nrf_ctrl_chan(u8 chan)
 | ||
| {
 | ||
|     if(nrf_get_connect_state()==0) return NRF_ERR;
 | ||
|     
 | ||
|     nrf_load_struct load={0};
 | ||
|     nrf_chan_struct c={0};
 | ||
|     c.chan=chan;
 | ||
|     c.times=0;
 | ||
|     u8 chan_old=g_nrf_env.channel_frequency;
 | ||
|     
 | ||
|     // 第一次发送是收不到回应的,因为从机已经改了信道
 | ||
|     nrf_packet_pack(&load,NRF_TYPE_CHAN,&c,sizeof(nrf_chan_struct));
 | ||
|     nrf_send_load(&load);
 | ||
|     
 | ||
|     // 这里修改信道后发送第二次
 | ||
|     nrf_set_chan(c.chan);
 | ||
|     c.times++;
 | ||
|     // 这次要是成功了则调频成功
 | ||
|     nrf_packet_pack(&load,NRF_TYPE_CHAN,&c,sizeof(nrf_chan_struct));
 | ||
|     if(nrf_send_load(&load)==NRF_OK)
 | ||
|     {
 | ||
|         return NRF_OK;
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|         // 设置回之前的信道
 | ||
|         nrf_set_chan(chan_old);
 | ||
|         return NRF_ERR;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // 通过协议发送负载数据,成功返回 NRF_OK
 | ||
| int nrf_send_load(nrf_load_struct *load)
 | ||
| {
 | ||
|     int ret=0;
 | ||
|     int time_out=0;
 | ||
|     int retry_times=0;
 | ||
|     // 交互成功设置为NRF_ERR,在收到对方返回后自动更新
 | ||
|     g_nrf_env.interaction_err=NRF_ERR;
 | ||
|     // 在发送的时候设置魔数
 | ||
|     do{
 | ||
|         load->magic_number=nrf_get_random();
 | ||
|     }while(load->magic_number==g_nrf_env.magic_number_send);
 | ||
|     g_nrf_env.magic_number_send=load->magic_number;
 | ||
|     // TODO 这里设置收到数据回调函数,用于接收对方的回应
 | ||
|     retry:
 | ||
|     nrf24l01_send(load);
 | ||
|     g_nrf_env.send_packet_all++;
 | ||
|     while(time_out<g_nrf_env.interaction_time_out)
 | ||
|     {
 | ||
|         if(g_nrf_env.interaction_err==NRF_OK) return NRF_OK;
 | ||
|         if(g_nrf_env.interaction_err!=NRF_ERR) return g_nrf_env.interaction_err;
 | ||
|         nrf_dalay_us(1);
 | ||
|         time_out++;
 | ||
|     }
 | ||
|     if(retry_times<g_nrf_env.retry_itmes)
 | ||
|     {
 | ||
|         g_nrf_env.send_packet_failed++;
 | ||
|         retry_times++;
 | ||
|         time_out=0;
 | ||
|         goto retry;
 | ||
|     }
 | ||
|     return NRF_TIMEOUT;
 | ||
| }
 | ||
| 
 | ||
| // 在接收到数据之后回复对方
 | ||
| int nrf_respond(nrf_load_struct *load)
 | ||
| {
 | ||
|     
 | ||
|     if(g_nrf_env.no_respond) return NRF_OK;
 | ||
|     int ret=0;
 | ||
|     int time_out=0;
 | ||
|     int retry_times=0;
 | ||
|     // 发送成功设置为0,在发送完成后自动置1
 | ||
|     g_nrf_env.send_ok=0;
 | ||
|     // 把魔数设置成和接收时相同
 | ||
|     load->magic_number=g_nrf_env.magic_number_recv;
 | ||
|     // 由于这个函数在中断中调用,因此不能在这里判断发送成功,
 | ||
|     // 先假设每次都发送成功,再由主机端来做重试操作
 | ||
|     nrf24l01_send(load);
 | ||
|     return NRF_OK;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // 设置是否回应,1,不回应,0,回应
 | ||
| int nrf_set_no_respond(int power)
 | ||
| {
 | ||
|     g_nrf_env.no_respond=power;
 | ||
|     return NRF_OK;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| // 打包帧,返回NRF_OK成功
 | ||
| int nrf_packet_pack(nrf_load_struct *load,u8 type,void *data,int data_len)
 | ||
| {
 | ||
|     if(data_len>29) return NRF_ERR;
 | ||
|     if(load==0) return NRF_ERR;
 | ||
|     load->len=data_len;
 | ||
|     load->type=type;
 | ||
|     memcpy(load->load,data,data_len);
 | ||
|     return NRF_OK;
 | ||
|     
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // 比较两个地址是否相同,是返回1
 | ||
| int nrf_addr_cmp(u8 addr1[5],u8 addr2[5])
 | ||
| {
 | ||
|     for(int i=0;i<5;i++)
 | ||
|     {
 | ||
|         if(addr1[i]!=addr2[i]) return 0;
 | ||
|     }
 | ||
|     return 1;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| // 接收到数据回调
 | ||
| void nrf_recv_cb(void *t)
 | ||
| {
 | ||
|     nrf_load_struct r={0};
 | ||
|     nrf24l01_read(&r);
 | ||
|     // TODO 接收到数据之后重置超时定时器
 | ||
|     u8 magic_number_old=g_nrf_env.magic_number_recv;
 | ||
|     g_nrf_env.magic_number_recv=r.magic_number;
 | ||
|     switch(r.type)
 | ||
|     {
 | ||
|         case NRF_TYPE_NULL:
 | ||
|             // TODO 是空操作,回复成功即可
 | ||
|             nrf_packet_pack(&r,NRF_TYPE_ANSWER,NRF_ANSWER_OK);
 | ||
|             nrf_respond(&r);
 | ||
|         break;
 | ||
|         case NRF_TYPE_CONN:
 | ||
|         {
 | ||
|             nrf_conn_struct *c=(nrf_conn_struct *)r.load;
 | ||
|             if(nrf_addr_cmp(c->addr_dst,g_nrf_env.addr_myself))
 | ||
|             {
 | ||
|                 nrf_packet_pack(&r,NRF_TYPE_ANSWER,NRF_ANSWER_OK);
 | ||
|                 nrf_respond(&r);
 | ||
|                 
 | ||
|                 // TODO 这里设置连接后的信道
 | ||
|                 nrf_set_addr(0,c->addr_src);
 | ||
|                 nrf_set_chan(c->chan);
 | ||
|             }
 | ||
|         }
 | ||
|         break;
 | ||
|         case NRF_TYPE_CHAN:
 | ||
|         {
 | ||
|             // 在与主句连接后可以切换信道
 | ||
|             nrf_chan_struct *c=(nrf_chan_struct *)r.load;
 | ||
|             if(nrf_get_connect_state())
 | ||
|             {
 | ||
|                 if(c->times==0)
 | ||
|                 {
 | ||
|                     // 第一次接收直接改信道,不回应
 | ||
|                     nrf_set_chan(c->chan);
 | ||
|                 } 
 | ||
|                 else if(c->times==1)
 | ||
|                 {
 | ||
|                     // 第二次回应成功
 | ||
|                     nrf_packet_pack(&r,NRF_TYPE_ANSWER,NRF_ANSWER_OK);
 | ||
|                     nrf_respond(&r);
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|         break;
 | ||
|         case NRF_TYPE_ANSWER:
 | ||
|         {
 | ||
|             // TODO 根据返回的错误类型设置交互状态
 | ||
|             if(g_nrf_env.magic_number_send==r.magic_number)
 | ||
|             {
 | ||
|                 u8 err=r.load[0];
 | ||
|                 g_nrf_env.interaction_err=err;
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 g_nrf_env.interaction_err=NRF_MISMATCH;
 | ||
|             }
 | ||
|         }
 | ||
|         break;
 | ||
|         case NRF_TYPE_DATA:
 | ||
|         {
 | ||
|             // 保存接收到的数据
 | ||
|             if(magic_number_old!=r.magic_number)
 | ||
|             {
 | ||
|                 for(int i=0;i<r.len;i++)
 | ||
|                 {
 | ||
|                     if(buff_save_byte(&g_buff,r.load[i])!=0)
 | ||
|                     {
 | ||
|                         printf("%s:buff overflow\r\n",__func__);
 | ||
|                     }
 | ||
|                 }
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 printf("%s:resave\r\n",__func__);
 | ||
|             }
 | ||
|             nrf_packet_pack(&r,NRF_TYPE_ANSWER,NRF_ANSWER_OK);
 | ||
|             nrf_respond(&r);
 | ||
|         }
 | ||
|         break;
 | ||
|         default:
 | ||
|         break;
 | ||
|     }
 | ||
|     
 | ||
| }
 | ||
| // 发送完成数据回调
 | ||
| void nrf_send_cb(void *t)
 | ||
| {
 | ||
|     g_nrf_env.send_ok=1;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 |