【沁恒CH582】 让蓝牙参与到控制中....
[复制链接]
上一次我们讨论了通过UART实现的控制代码,我们可以将UART平行变易成由BLE完成的版本。方法仍然同样的简单,我们可以部分修改BLE_UART程序中的一部分。
在peripheral_main.c 中可以找到这一部分
__HIGH_CODE
void Main_Circulation() {
while (1) {
TMOS_SystemProcess();
app_uart_process();
}
}
可以定位到uart的处理函数。我们进去观察一下:
void app_uart_process(void)
{
UINT32 irq_status;
SYS_DisableAllIrq( &irq_status );
if(uart_rx_flag)
{
tmos_start_task( Peripheral_TaskID, UART_TO_BLE_SEND_EVT,2);
uart_rx_flag = false;
}
SYS_RecoverIrq( irq_status );
//tx process
if(R8_UART3_TFC < UART_FIFO_SIZE)
{
app_drv_fifo_read_to_same_addr(&app_uart_tx_fifo,(uint8_t *)&R8_UART3_THR,UART_FIFO_SIZE-R8_UART3_TFC);
}
}
与我们预想的并不相同,但是大体上可以理解成当uart_rx_flag 标志位被置位之后将会启动进程Peripheral_ProcessEvent 特殊的响应任务UART_TO_BLE_SEND_EVT 。但是之后我们可以看到UART3的消息响应函数:当消息收到的时候就会设置uart_rx_flag ,由实时系统调度实现对这个消息的响应。
__INTERRUPT
__HIGH_CODE
void UART3_IRQHandler(void) {
uint16_t error;
switch( UART3_GetITFlag()) {
case UART_II_LINE_STAT:
UART3_GetLinSTA();
break;
case UART_II_RECV_RDY:
case UART_II_RECV_TOUT:
error = app_drv_fifo_write_from_same_addr(&app_uart_rx_fifo,(uint8_t *)&R8_UART3_RBR,R8_UART3_RFC);
if(error != APP_DRV_FIFO_RESULT_SUCCESS) {
for(uint8_t i =0;i<R8_UART3_RFC;i++) {
//fifo full,put to fifo black hole
for_uart_rx_black_hole = R8_UART3_RBR;
}
}
uart_rx_flag = true;
break;
case UART_II_THR_EMPTY:
break;
case UART_II_MODEM_CHG:
break;
default:
break;
}
}
接下来我们可以找到这个进程的具体定义部分:
/*********************************************************************
* @fn Peripheral_ProcessEvent
*
* @brief Peripheral Application Task event processor. This function
* is called to process all events for the task. Events
* include timers, messages and any other user defined events.
*
* @param task_id - The TMOS assigned task ID.
* @param events - events to process. This is a bit map and can
* contain more than one event.
*
* @return events not processed
*/
uint16 Peripheral_ProcessEvent( uint8 task_id, uint16 events )
{
static attHandleValueNoti_t noti;
// VOID task_id; // TMOS required parameter that isn't used in this function
if ( events & SYS_EVENT_MSG ){
uint8 *pMsg;
if ( (pMsg = tmos_msg_receive( Peripheral_TaskID )) != NULL ){
Peripheral_ProcessTMOSMsg( (tmos_event_hdr_t *)pMsg );
// Release the TMOS message
tmos_msg_deallocate( pMsg );
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
if ( events & SBP_START_DEVICE_EVT ){
// Start the Device
GAPRole_PeripheralStartDevice( Peripheral_TaskID, &Peripheral_BondMgrCBs, &Peripheral_PeripheralCBs );
return ( events ^ SBP_START_DEVICE_EVT );
}
if ( events & SBP_PARAM_UPDATE_EVT )
{
// Send connect param update request
GAPRole_PeripheralConnParamUpdateReq( peripheralConnList.connHandle,
DEFAULT_DESIRED_MIN_CONN_INTERVAL,
DEFAULT_DESIRED_MAX_CONN_INTERVAL,
DEFAULT_DESIRED_SLAVE_LATENCY,
DEFAULT_DESIRED_CONN_TIMEOUT,
Peripheral_TaskID);
// GAPRole_PeripheralConnParamUpdateReq( peripheralConnList.connHandle,
// 10,
// 20,
// 0,
// 400,
// Peripheral_TaskID);
return (events ^ SBP_PARAM_UPDATE_EVT);
}
///////////////// 这里是关键 /////////////////////////////
if(events & UART_TO_BLE_SEND_EVT)
{
static uint16_t read_length=0;;
uint8_t result=0xff;
switch(send_to_ble_state){
case SEND_TO_BLE_TO_SEND:
//notify is not enabled
if(!ble_uart_notify_is_ready(peripheralConnList.connHandle)){
if(peripheralConnList.connHandle == GAP_CONNHANDLE_INIT){
//connection lost, flush rx fifo here
app_drv_fifo_flush(&app_uart_rx_fifo);
}
break;
}
read_length = ATT_GetMTU(peripheralConnList.connHandle)-3;
if(app_drv_fifo_length(&app_uart_rx_fifo)>= read_length){
PRINT("FIFO_LEN:%d\r\n",app_drv_fifo_length(&app_uart_rx_fifo));
// 这里得到具体的数据,保存在to_test_buffer
result = app_drv_fifo_read(&app_uart_rx_fifo,to_test_buffer,&read_length);
uart_to_ble_send_evt_cnt = 0;
}else{
if(uart_to_ble_send_evt_cnt>10){
result = app_drv_fifo_read(&app_uart_rx_fifo,to_test_buffer,&read_length);
uart_to_ble_send_evt_cnt =0;
}else{
tmos_start_task( Peripheral_TaskID, UART_TO_BLE_SEND_EVT,4);
uart_to_ble_send_evt_cnt ++;
PRINT("NO TIME OUT\r\n");
}
}
if(APP_DRV_FIFO_RESULT_SUCCESS == result){
noti.len = read_length;
noti.pValue = GATT_bm_alloc( peripheralConnList.connHandle, ATT_HANDLE_VALUE_NOTI, noti.len, NULL, 0 );
if(noti.pValue != NULL){
tmos_memcpy( noti.pValue, to_test_buffer, noti.len );
result = ble_uart_notify( peripheralConnList.connHandle, ¬i,0 );
if( result != SUCCESS )
{
PRINT("R1:%02x\r\n",result);
send_to_ble_state = SEND_TO_BLE_SEND_FAILED;
GATT_bm_free( (gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI );
tmos_start_task( Peripheral_TaskID, UART_TO_BLE_SEND_EVT,2);
}else{
send_to_ble_state = SEND_TO_BLE_TO_SEND;
//app_fifo_write(&app_uart_tx_fifo,to_test_buffer,&read_length);
//app_drv_fifo_write(&app_uart_tx_fifo,to_test_buffer,&read_length);
read_length = 0;
tmos_start_task( Peripheral_TaskID, UART_TO_BLE_SEND_EVT,2);
}
}else{
send_to_ble_state = SEND_TO_BLE_ALLOC_FAILED;
tmos_start_task( Peripheral_TaskID, UART_TO_BLE_SEND_EVT,2);
}
}else{
//send_to_ble_state = SEND_TO_BLE_FIFO_EMPTY;
}
break;
case SEND_TO_BLE_ALLOC_FAILED:
case SEND_TO_BLE_SEND_FAILED:
noti.len = read_length;
noti.pValue = GATT_bm_alloc( peripheralConnList.connHandle, ATT_HANDLE_VALUE_NOTI, noti.len, NULL, 0 );
if(noti.pValue != NULL){
tmos_memcpy( noti.pValue, to_test_buffer, noti.len );
result = ble_uart_notify( peripheralConnList.connHandle, ¬i,0 );
if( result != SUCCESS )
{
PRINT("R2:%02x\r\n",result);
send_to_ble_state = SEND_TO_BLE_SEND_FAILED;
GATT_bm_free( (gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI );
tmos_start_task( Peripheral_TaskID, UART_TO_BLE_SEND_EVT,2);
}else{
send_to_ble_state = SEND_TO_BLE_TO_SEND;
//app_drv_fifo_write(&app_uart_tx_fifo,to_test_buffer,&read_length);
read_length = 0;
tmos_start_task( Peripheral_TaskID, UART_TO_BLE_SEND_EVT,2);
}
}else{
send_to_ble_state = SEND_TO_BLE_ALLOC_FAILED;
tmos_start_task( Peripheral_TaskID, UART_TO_BLE_SEND_EVT,2);
}
break;
default:
break;
}
return (events ^ UART_TO_BLE_SEND_EVT);
}
// Discard unknown events
return 0;
}
在响应事件的时候将会进入if(events & UART_TO_BLE_SEND_EVT) 分支,可以看到首先从fifo 中读取到当前输入的内容保存在to_test_buffer 中,然后使用GATT_bm_alloc 构建数据包,并使用ble_uart_notify 发送数据。
那么按照这个思路,我们有两种响应方式,第一种,直接在中断响应函数中响应输入的信息,另一种则是在此处的程序中另加一个分支来响应输入的消息。
一般地,我们希望对于输入等通信消息的接收响应尽可能简短,而将更加细节的任务放在任务或者事件响应中,那么我们可以改动其中部分代码:为了保证逻辑的清晰性,我只是摘取了主要框架部分,能够让大家更好地看清逻辑关系:
if(APP_DRV_FIFO_RESULT_SUCCESS == result){
noti.len = read_length;
noti.pValue = GATT_bm_alloc( peripheralConnList.connHandle, ATT_HANDLE_VALUE_NOTI, noti.len, NULL, 0 );
if(noti.pValue != NULL){
tmos_memcpy( noti.pValue, to_test_buffer, noti.len );
for(int i = 0; i< noti.len;i++)
{
switch(noti.pValue)
{
case 'A':
//...
}
}
result = ble_uart_notify( peripheralConnList.connHandle, ¬i,0 );
下面给出上文中//... 部分应当写明的代码:
case 'A':case 'B':case 'C':case 'D':
state |= 1<<(RxBuff - 'A');
break;
case 'E':case 'F':case 'G':case 'H':
state &= 0xFF^1<<(RxBuff - 'A');
break;
default:
break;
这样我们就快速实现了一个蓝牙控制的开关设备!
理论上来说还可以通过新建任务等完成更加复杂的功能,对于其中使用的抢占式实时系统以及蓝牙的一些具体细节,且听下回分解。
|