移植外设异步传输libuarte到ble_central/ble_app_uart_c的例程里面的,也是蓝牙做主设备时的模板例程,不移植真不知道这么麻烦,并且问题千奇百怪,为了未来的程序员大佬在进阶的时候少掉几根头发,我经过一天多的时间终于在Nordic大佬的帮助下成功移植,并且这个Libuarte传输1个字节的时间比ble_app_uart_c例程里面的1个字节1个字节存放到tx fifo里面再发送出去节省了1个bit(8us)的时间,而且这个串口例程有1个非常非常大的缺陷就是,如果你传输的数据很大,比如一张图片的照片,当在输入输出波特率一致的情况下就会出现tx fifo满的情况,就会报错,并且传输每个字节的间隔不稳定,可能大可能小,并且在传输10个Bit(1起始、8数据、1停止位)之后还存在8us的间隔有时候会170us(在数据大的情况下);
当然,从解决方案上面有以下几种:
1.硬流控(这个方案很可靠,很安全,但是主要看你的设备是否把该引脚接出来)
2.在因为tx fifo溢出报错的情况下,可以重新尝试放入到fifo,达到一定次数如果还没放入fifo成功,就再进行丢数据处理
3.用软流控,需要输入输出确定好交互协议
4.如果有2个串口U1和U2,接收数据的串口U2和从外部传输进来数据的设备U3都设置成2个stop bit,同时输出的串口U1设置成1个bit位置,那么在传输数据量不是特别大(如>30000字节)的情况下可使用这个解决方案
5.如果输入端的传输速率不是特别特别块的话,可以采用Nordic的外设libuarte,这个方案非常好,传输数据间隔很稳定,传输10个bit的时间正好86us,很快也很准。
我在移植过程中,遇到的问题有以下:
1.由于协议栈默认使用的是rtc0,所以移植的时候需要改变libuarte的使用接口,改成使用RTC2,还有就是libuarte的timer0也被占用了,所需要libuarte需要使用其他的timer,我改成的是timer1,在sdk_config.h里面也需要做相应的改动
#define NRFX_RTC_ENABLED 1
#define NRFX_RTC0_ENABLED 0
#define NRFX_RTC1_ENABLED 0
#define NRFX_RTC2_ENABLED 1
#define RTC_ENABLED 1
#ifndef RTC0_ENABLED
#define RTC0_ENABLED 0
#endif
// <q> RTC1_ENABLED - Enable RTC1 instance
#ifndef RTC1_ENABLED
#define RTC1_ENABLED 0
#endif
#ifndef RTC2_ENABLED
#define RTC2_ENABLED 1
#endif
#ifndef TIMER_ENABLED
#define TIMER_ENABLED 1
#endif
#ifndef TIMER0_ENABLED
#define TIMER0_ENABLED 0
#endif
// <q> TIMER1_ENABLED - Enable TIMER1 instance
#ifndef TIMER1_ENABLED
#define TIMER1_ENABLED 1
#endif
// <q> TIMER2_ENABLED - Enable TIMER2 instance
#ifndef TIMER2_ENABLED
#define TIMER2_ENABLED 0
#endif
// <q> TIMER3_ENABLED - Enable TIMER3 instance
#ifndef TIMER3_ENABLED
#define TIMER3_ENABLED 0
#endif
// <q> TIMER4_ENABLED - Enable TIMER4 instance
#ifndef TIMER4_ENABLED
#define TIMER4_ENABLED 0
#endif
#ifndef APP_TIMER_ENABLED
#define APP_TIMER_ENABLED 1
#endif
#ifndef NRFX_TIMER0_ENABLED
#define NRFX_TIMER0_ENABLED 0
#endif
// <q> NRFX_TIMER1_ENABLED - Enable TIMER1 instance
#ifndef NRFX_TIMER1_ENABLED
#define NRFX_TIMER1_ENABLED 1
#endif
// <q> NRFX_TIMER2_ENABLED - Enable TIMER2 instance
#ifndef NRFX_TIMER2_ENABLED
#define NRFX_TIMER2_ENABLED 0
#endif
// <q> NRFX_TIMER3_ENABLED - Enable TIMER3 instance
#ifndef NRFX_TIMER3_ENABLED
#define NRFX_TIMER3_ENABLED 0
#endif
// <q> NRFX_TIMER4_ENABLED - Enable TIMER4 instance
#ifndef NRFX_TIMER4_ENABLED
#define NRFX_TIMER4_ENABLED 0
#endif
#ifndef NRF_LIBUARTE_ASYNC_WITH_APP_TIMER
#define NRF_LIBUARTE_ASYNC_WITH_APP_TIMER 1
#endif
#ifndef NRF_LIBUARTE_DRV_HWFC_ENABLED
#define NRF_LIBUARTE_DRV_HWFC_ENABLED 0
#endif
// <q> NRF_LIBUARTE_DRV_UARTE0 - UARTE0 instance
#ifndef NRF_LIBUARTE_DRV_UARTE0
#define NRF_LIBUARTE_DRV_UARTE0 1
#endif
// <q> NRF_LIBUARTE_DRV_UARTE1 - UARTE1 instance
#ifndef NRF_LIBUARTE_DRV_UARTE1
#define NRF_LIBUARTE_DRV_UARTE1 0
#endif
除了sdk_config.h的改变还需要在main.c里面修改
NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 0, 1, 2, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 255, 3);
第三个参数和第四个参数分别代表使用的timer1和RTC2
libuarte串口初始化uart_init,源码里面的那个使用fifo的那个uart_init需要注释掉
static void uart_init(void)
{
ret_code_t err_code;
nrf_libuarte_async_config_t nrf_libuarte_async_config = {
.tx_pin = TX_PIN_NUMBER,
.rx_pin = RX_PIN_NUMBER,
.baudrate = NRF_UARTE_BAUDRATE_115200,
.parity = NRF_UARTE_PARITY_EXCLUDED,
.hwfc = NRF_UARTE_HWFC_DISABLED,
.timeout_us = 100,
.int_prio = APP_IRQ_PRIORITY_LOW
};
err_code = nrf_libuarte_async_init(&libuarte, &nrf_libuarte_async_config, uart_event_handler, (void *)&libuarte);
APP_ERROR_CHECK(err_code);
nrf_libuarte_async_enable(&libuarte);
err_code = nrf_libuarte_async_tx(&libuarte, text, text_size);
APP_ERROR_CHECK(err_code);
}
main函数里面的代码
int main(void)
{
// Initialize.
log_init();
timer_init();
uart_init();
buttons_leds_init();
db_discovery_init();
power_management_init();
ble_stack_init();
gatt_init();
nus_c_init();
scan_init();
// Start execution.
// printf("BLE UART central example started.\r\n");
NRF_LOG_INFO("BLE UART central example started.");
scan_start();
// Enter main loop.
for (;;)
{
idle_state_handle();
}
}
如果有需要源码的哥们可以私信我,我发你。
下载这些Nordic官方例程的网站链接:nRF5 SDK downloads - nordicsemi.com
我下载的是17.1.0的,我不太确定新版本是否更好,大家可以尝试一下
每天都在进步,各位加油!!!!!!