#include "nrf.h" #include "24l01.h" #include "buff.h" #include "rthw.h" #include "stdio.h" #include "string.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; // 本机地址 uint8_t addr_myself[5]; // 目标机地址 uint8_t addr_dst[5]; // 最近发送使用的魔数 uint8_t magic_number_send; // 最近接收使用的魔数 uint8_t magic_number_recv; } nrf_env_struct; static nrf_env_struct g_nrf_env = {0}; static data_buff g_buff = {0}; static const uint8_t g_dst_addr[TX_ADR_WIDTH] = {0x34, 0x43, 0x10, 0x10, 0x01}; // 发送地址 static const uint8_t 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 uint8_t *my, const uint8_t *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(uint8_t 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(uint8_t 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; uint8_t 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, uint8_t 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(uint8_t addr1[5], uint8_t 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 接收到数据之后重置超时定时器 uint8_t 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) { uint8_t 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; }