1.目的
分析蓝牙串口的例子
2.分析
在实际应用中经常使用串口,下面我们就来分析下串口例子
3.平台:
sofeDevice : s110_nrf51_8.0.0_softdevice.hex
协议栈版本:SDK10.0.0
编译软件:keil 5.12
硬件平台:nrf51822最小系统
例子:SDK 10.0.0\examples\ble_peripheral\ble_app_uart\pca10028\s110\arm4
4.步骤
int main(void)
{
uint32_t err_code;
bool erase_bonds;
uint8_t start_string[] = START_STRING;
// Initialize.
APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);
uart_init();
buttons_leds_init(&erase_bonds);
ble_stack_init();
gap_params_init();
services_init();
advertising_init();
conn_params_init();
printf("%s",start_string);
err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
APP_ERROR_CHECK(err_code);
// Enter main loop.
for (;;)
{
power_manage();
}
}
a.串口初始化
uart_init();
把APP_UART_FLOW_CONTROL_ENABLED ==》APP_UART_FLOW_CONTROL_DISABLED 不使用流控
在pca10028.h 中定义串口的管脚,如下:
#define RX_PIN_NUMBER 11
#define TX_PIN_NUMBER 9
#define CTS_PIN_NUMBER 10
#define RTS_PIN_NUMBER 8
#define HWFC false
static void uart_init(void)
{
uint32_t err_code;
const app_uart_comm_params_t comm_params =
{
RX_PIN_NUMBER,
TX_PIN_NUMBER,
RTS_PIN_NUMBER,
CTS_PIN_NUMBER,
APP_UART_FLOW_CONTROL_DISABLED,// APP_UART_FLOW_CONTROL_ENABLED
false,
UART_BAUDRATE_BAUDRATE_Baud38400
};
APP_UART_FIFO_INIT( &comm_params,
UART_RX_BUF_SIZE,
UART_TX_BUF_SIZE,
uart_event_handle,
APP_IRQ_PRIORITY_LOW,
err_code);
APP_ERROR_CHECK(err_code);
}
定义了接收和发送缓冲区的大小:
#define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE 256 /**< UART RX buffer size. */
然后初始化哪个串口,串口发送和接收缓冲区,串口回调函数,串口优先级,代码如下
#define APP_UART_FIFO_INIT(P_COMM_PARAMS, RX_BUF_SIZE, TX_BUF_SIZE, EVT_HANDLER, IRQ_PRIO, ERR_CODE) \
do \
{ \
app_uart_buffers_t buffers; \
static uint8_t rx_buf[RX_BUF_SIZE]; \
static uint8_t tx_buf[TX_BUF_SIZE]; \
\
buffers.rx_buf = rx_buf; \
buffers.rx_buf_size = sizeof (rx_buf); \
buffers.tx_buf = tx_buf; \
buffers.tx_buf_size = sizeof (tx_buf); \
ERR_CODE = app_uart_init(P_COMM_PARAMS, &buffers, EVT_HANDLER, IRQ_PRIO); \
} while (0)
uint32_t app_uart_init(const app_uart_comm_params_t * p_comm_params,
app_uart_buffers_t * p_buffers,
app_uart_event_handler_t event_handler,
app_irq_priority_t irq_priority)
{
uint32_t err_code;
m_event_handler = event_handler;
if (p_buffers == NULL)
{
return NRF_ERROR_INVALID_PARAM;
}
// Configure buffer RX buffer.
err_code = app_fifo_init(&m_rx_fifo, p_buffers->rx_buf, p_buffers->rx_buf_size);
if (err_code != NRF_SUCCESS)
{
// Propagate error code.
return err_code;
}
// Configure buffer TX buffer.
err_code = app_fifo_init(&m_tx_fifo, p_buffers->tx_buf, p_buffers->tx_buf_size);
if (err_code != NRF_SUCCESS)
{
// Propagate error code.
return err_code;
}
nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG;
config.baudrate = (nrf_uart_baudrate_t)p_comm_params->baud_rate;
config.hwfc = (p_comm_params->flow_control == APP_UART_FLOW_CONTROL_DISABLED) ?
NRF_UART_HWFC_DISABLED : NRF_UART_HWFC_ENABLED;
config.interrupt_priority = irq_priority;
config.parity = p_comm_params->use_parity ? NRF_UART_PARITY_INCLUDED : NRF_UART_PARITY_EXCLUDED;
config.pselcts = p_comm_params->cts_pin_no;
config.pselrts = p_comm_params->rts_pin_no;
config.pselrxd = p_comm_params->rx_pin_no;
config.pseltxd = p_comm_params->tx_pin_no;
err_code = nrf_drv_uart_init(&config, uart_event_handler);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
nrf_drv_uart_rx_enable();
return nrf_drv_uart_rx(rx_buffer,1);
}
配置发送 接收缓冲区,配置具体的寄存器,开中断等等。
看nrf_drv_uart_init();
把 m_cb.handler = event_handler; m_cb.handler 指向回调函数
ret_code_t nrf_drv_uart_init(nrf_drv_uart_config_t const * p_config,
nrf_uart_event_handler_t event_handler)
{
if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED)
{
return NRF_ERROR_INVALID_STATE;
}
if (p_config == NULL)
{
p_config = &m_default_config;
}
#ifdef NRF52
m_cb.use_easy_dma = p_config->use_easy_dma;
#endif
apply_config(p_config);
m_cb.handler = event_handler;
m_cb.p_context = p_config->p_context;
if (m_cb.handler)
{
interrupts_enable(p_config->interrupt_priority);
}
uart_enable();
m_cb.rx_buffer_length = 0;
m_cb.tx_buffer_length = 0;
m_cb.state = NRF_DRV_STATE_INITIALIZED;
m_cb.rx_enabled = false;
return NRF_SUCCESS;
}
串口中断函数 因为没有定义UARTE_IN_USE 也没有定义 UART_IN_USE
所以只有 CODE_FOR_UART定义了
#if (defined(UARTE_IN_USE) && defined(UART_IN_USE))
// UARTE and UART combined
#define CODE_FOR_UARTE(code) if (m_cb.use_easy_dma) { code }
#define CODE_FOR_UART(code) else { code }
#elif (defined(UARTE_IN_USE) && !defined(UART_IN_USE))
// UARTE only
#define CODE_FOR_UARTE(code) { code }
#define CODE_FOR_UART(code)
#elif (!defined(UARTE_IN_USE) && defined(UART_IN_USE))
// UART only
#define CODE_FOR_UARTE(code)
#define CODE_FOR_UART(code) { code }
#else
#error "Wrong configuration."
#endif
void UART0_IRQHandler(void)
{
CODE_FOR_UARTE
(
if (nrf_uarte_event_check(NRF_UARTE0, NRF_UARTE_EVENT_ERROR))
{
nrf_drv_uart_event_t event;
nrf_uarte_event_clear(NRF_UARTE0, NRF_UARTE_EVENT_ERROR);
event.type = NRF_DRV_UART_EVT_ERROR;
event.data.error.error_mask = nrf_uarte_errorsrc_get_and_clear(NRF_UARTE0);
event.data.error.rxtx.bytes = nrf_uarte_rx_amount_get(NRF_UARTE0);
event.data.error.rxtx.p_data = m_cb.p_rx_buffer;
//abort transfer
m_cb.rx_buffer_length = 0;
m_cb.handler(&event,m_cb.p_context);
}
else if (nrf_uarte_event_check(NRF_UARTE0, NRF_UARTE_EVENT_ENDRX))
{
nrf_uarte_event_clear(NRF_UARTE0, NRF_UARTE_EVENT_ENDRX);
uint8_t amount = nrf_uarte_rx_amount_get(NRF_UARTE0);
if (amount == m_cb.rx_buffer_length)
{
rx_done_event(amount);
}
}
if (nrf_uarte_event_check(NRF_UARTE0, NRF_UARTE_EVENT_RXTO))
{
nrf_uarte_event_clear(NRF_UARTE0, NRF_UARTE_EVENT_RXTO);
if (m_cb.rx_buffer_length)
{
rx_done_event(nrf_uarte_rx_amount_get(NRF_UARTE0));
}
}
if (nrf_uarte_event_check(NRF_UARTE0, NRF_UARTE_EVENT_ENDTX))
{
nrf_uarte_event_clear(NRF_UARTE0, NRF_UARTE_EVENT_ENDTX);
if (m_cb.tx_buffer_length)
{
tx_done_event(nrf_uarte_tx_amount_get(NRF_UARTE0));
}
}
)
CODE_FOR_UART(
if (nrf_uart_int_enable_check(NRF_UART0, NRF_UART_INT_MASK_ERROR) &&
nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_ERROR))
{
nrf_drv_uart_event_t event;
nrf_uart_event_clear(NRF_UART0, NRF_UART_EVENT_ERROR);
nrf_uart_int_disable(NRF_UART0, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR);
if (!m_cb.rx_enabled)
{
nrf_uart_task_trigger(NRF_UART0, NRF_UART_TASK_STOPRX);
}
event.type = NRF_DRV_UART_EVT_ERROR;
event.data.error.error_mask = nrf_uart_errorsrc_get_and_clear(NRF_UART0);
event.data.error.rxtx.bytes = m_cb.rx_buffer_length;
event.data.error.rxtx.p_data = m_cb.p_rx_buffer;
//abort transfer
m_cb.rx_buffer_length = 0;
m_cb.handler(&event,m_cb.p_context);
}
else if (nrf_uart_int_enable_check(NRF_UART0, NRF_UART_INT_MASK_RXDRDY) &&
nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_RXDRDY))
{
rx_byte();
if (m_cb.rx_buffer_length == m_cb.rx_counter)
{
if (!m_cb.rx_enabled)
{
nrf_uart_task_trigger(NRF_UART0, NRF_UART_TASK_STOPRX);
}
nrf_uart_int_disable(NRF_UART0, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR);
rx_done_event(m_cb.rx_counter);
}
}
if (nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_TXDRDY))
{
if ((m_cb.tx_buffer_length > m_cb.tx_counter))
{
tx_byte();
}
else
{
nrf_uart_event_clear(NRF_UART0, NRF_UART_EVENT_TXDRDY);
if (m_cb.tx_buffer_length)
{
tx_done_event(m_cb.tx_buffer_length);
}
}
}
if (nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_RXTO))
{
nrf_uart_event_clear(NRF_UART0, NRF_UART_EVENT_RXTO);
// RXTO event may be triggered as a result of abort call. In th
if (m_cb.rx_enabled)
{
nrf_uart_task_trigger(NRF_UART0, NRF_UART_TASK_STARTRX);
}
if (m_cb.rx_buffer_length)
{
rx_done_event(m_cb.rx_counter);
}
}
)
}
发送数据并且缓冲区没有满的时候就是产生超时事件,
然后调用 rx_done_event(m_cb.rx_counter);
__STATIC_INLINE void rx_done_event(uint8_t bytes)
{
nrf_drv_uart_event_t event;
event.type = NRF_DRV_UART_EVT_RX_DONE;
event.data.rxtx.bytes = bytes;
event.data.rxtx.p_data = m_cb.p_rx_buffer;
m_cb.rx_buffer_length = 0;
m_cb.handler(&event,m_cb.p_context);
}
所以这里会产生uart_event_handle();函数
看回调函数uart_event_handle();
当有数据来了并且已“\n” 数据长度大于20,就会通过串口服务发送出去。
在这里我们添加一天串口打印数据语句,printf("%s",data_array);
void uart_event_handle(app_uart_evt_t * p_event)
{
static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
static uint8_t index = 0;
uint32_t err_code;
switch (p_event->evt_type)
{
case APP_UART_DATA_READY:
UNUSED_VARIABLE(app_uart_get(&data_array[index]));
index++;
if ((data_array[index - 1] == '\n') || (index >= (BLE_NUS_MAX_DATA_LEN)))
{
printf("%s",data_array); //添加发送语句
err_code = ble_nus_string_send(&m_nus, data_array, index);
if (err_code != NRF_ERROR_INVALID_STATE)
{
APP_ERROR_CHECK(err_code);
}
index = 0;
}
break;
case APP_UART_COMMUNICATION_ERROR:
APP_ERROR_HANDLER(p_event->data.error_communication);
break;
case APP_UART_FIFO_ERROR:
APP_ERROR_HANDLER(p_event->data.error_code);
break;
default:
break;
}
}
实验:download the code 可以看到打印出 Start... 表示发送成功。
串口发送框写“abcdefghijklmnopqrst\n” (注意“\n”结尾并且发送数据的长度要大约等于20,这样程序才会返回,具体看uart_event_handle()函数)点击发送,
可以看到数据显示框里显示 “abcdefghijklmnopqrst” 程序里面发送什么 回复什么。现在发送和回复一致 ,表示正确
OK。。。。实验完成。。。。。