做網(wǎng)站建設(shè)的公司有哪些內(nèi)容房地產(chǎn)估價師考試
在官網(wǎng)下載SDK后(以Mesh SDK為例)使用Eclipse打開,對應MCU的配置文件在app_config_8258.h,默認的HCI接口是HCI_USE_NONE,如果改成HCI_USE_UART后可以通過串口收發(fā)數(shù)據(jù),此時默認接收函數(shù)處理的是以Telink的協(xié)議格式收到的SIG model 命令,函數(shù)原型為blc_rx_from_uart(),這個主要用在Gateway工程中。
8258支持一個串口外設(shè),可以不使用HCI_ACCESS宏,自己定義串口相關(guān),以便于連接其他模塊等,收發(fā)自定義數(shù)據(jù)。
用戶相關(guān)的配置可以放在user_app_config.h文件中,比如需要定義一下Tx和Rx引腳。
#define UART_TX_PIN UART_TX_PB1
#define UART_RX_PIN UART_RX_PA0
串口可以使用的引腳在硬件設(shè)計手冊中查找。
其次是在user_app.h中定義串口需要的相關(guān)結(jié)構(gòu)體和宏定義,其中user_uart_data_t結(jié)構(gòu)體為單次DMA接收的數(shù)據(jù)區(qū)內(nèi)容,dma_len必須是4字節(jié),在收到數(shù)據(jù)時表示接收到數(shù)據(jù)的長度;user_uart_que_t為串口數(shù)據(jù)處理的結(jié)構(gòu)體,采用循環(huán)隊列控制接收和發(fā)送,里面的rx_irq_cnt和tx_irq_cnt只是用來記錄進入中斷的次數(shù),可以通過BDT工具讀取判斷是否成功收發(fā)數(shù)據(jù),無實際意義。
#define USER_UART_DATA_LEN 12
#define USER_UART_DMA_LEN 4typedef struct{unsigned int dma_len;unsigned char data[USER_UART_DATA_LEN];
}user_uart_data_t;typedef struct{unsigned char rx_rear;unsigned char rx_front;unsigned char tx_rear;unsigned char tx_front;u16 rx_irq_cnt;u16 tx_irq_cnt;user_uart_data_t *p_rx_buf;user_uart_data_t *p_tx_buf;
}user_uart_que_t;
另外user_uart_data_t結(jié)構(gòu)體的大小必須是16的整數(shù)倍,因為在設(shè)置接收緩沖的時候會用接收緩沖區(qū)的長度除以16。
串口的初始化放在Mesh的初始化函數(shù)user_init中:
串口相關(guān)變量定義:
user_uart_data_t user_uart_recv_data[USER_MAX_QUE_LEN];
user_uart_data_t user_uart_trans_data[USER_MAX_QUE_LEN];
user_uart_que_t user_uart_que = {0};
const u16 UART_TX_LEN_MAX = sizeof(user_uart_data_t);
串口的初始化函數(shù)原型放在user_app.c中:
void user_uart_drv_init(void)
{user_uart_que_init();uart_recbuff_init( (unsigned char *)&user_uart_recv_data[0], sizeof(user_uart_recv_data), (unsigned char *)&user_uart_trans_data[0]);uart_gpio_set(UART_TX_PIN, UART_RX_PIN);uart_reset(); //will reset uart digital registers from 0x90 ~ 0x9f, so uart setting must set after this reset//baud rate: 115200uart_init(30, 8, PARITY_NONE, STOP_BIT_ONE);uart_dma_enable(1, 1); //uart data in hardware buffer moved by dma, so we need enable them firstirq_set_mask(FLD_IRQ_DMA_EN);dma_chn_irq_enable(FLD_DMA_CHN_UART_RX | FLD_DMA_CHN_UART_TX, 1); //uart Rx/Tx dma irq enable
}
串口接收處理函數(shù)通過判斷user_uart_que.rx_rear和user_uart_que.rx_front變量是否相等,來判斷接收緩沖隊列中是否有未處理的數(shù)據(jù),主要更改的是user_uart_que.rx_rear變量,由于是循環(huán)隊列,中斷處理函數(shù)在隊列已滿時也需要改變user_uart_que.rx_rear的值,因此串口接收處理函數(shù)中改變user_uart_que.rx_rear的值時需要通過開關(guān)中斷的方式處理一下。同樣串口發(fā)送處理函數(shù)中是通過user_uart_que.tx_front和user_uart_que.tx_rear的值是否相等來判斷是否有待發(fā)送的數(shù)據(jù),同時也要判斷一下串口是否空閑。
int user_rx_from_uart (void)
{u8 curr_p = 0;user_uart_data_t *p_data = NULL;uart_ErrorCLR();if(user_uart_que.rx_front != user_uart_que.rx_rear){u32 r = irq_disable();curr_p = user_uart_que.rx_rear;user_uart_que.rx_rear = (user_uart_que.rx_rear + 1) % USER_MAX_QUE_LEN;irq_restore(r);p_data = &user_uart_recv_data[curr_p];user_recv_data_process(p_data);//對接收到的數(shù)據(jù)進行處理}return 0;
}int user_tx_to_uart (void)
{if((user_uart_que.tx_front != user_uart_que.tx_rear) && (!uart_tx_is_busy ())){if(uart_Send(user_uart_trans_data[user_uart_que.tx_rear].data, user_uart_trans_data[user_uart_que.tx_rear].dma_len)){user_uart_que.tx_rear = (user_uart_que.tx_rear + 1) % USER_MAX_QUE_LEN;}}return 0;
}
待發(fā)送數(shù)據(jù)入列函數(shù),如果有數(shù)據(jù)需要發(fā)送,可以通過調(diào)用user_uart_que_push函數(shù)來入列。
void user_uart_que_push(user_uart_data_t *data)
{memcpy((unsigned char *)&user_uart_trans_data[user_uart_que.tx_front],(unsigned char *)data,(data->dma_len + USER_UART_DMA_LEN));user_uart_que.tx_front = (user_uart_que.tx_front + 1) % USER_MAX_QUE_LEN;if(user_uart_que.tx_front == user_uart_que.tx_rear){user_uart_que.tx_rear = (user_uart_que.tx_rear + 1) % USER_MAX_QUE_LEN;}
}
然后在main.c中的irq_uart_handle函數(shù)中添加串口的中斷處理函數(shù),在收到一幀數(shù)據(jù)時,需要設(shè)置一下串口DMA接收緩沖的地址,指向下一個空閑的數(shù)據(jù)接收區(qū)域,這樣的話就不用把接收到的數(shù)據(jù)拷貝到另外的地方,這也就是為什么需要用隊列的方式接收數(shù)據(jù)。
在串口中斷中主要更改的是串口隊列中的user_uart_que.rx_front變量,用于指示下一個接收的緩沖區(qū),當user_uart_que.rx_front加1和user_uart_que.rx_rear變量相等時,意味著接收緩沖區(qū)滿了,接收到的數(shù)據(jù)一直沒有被處理,此時user_uart_que.rx_rear變量也要加1,也就是覆蓋掉最早接收到的數(shù)據(jù)。
_attribute_ram_code_ void user_irq_uart_handle()
{unsigned char irqS = reg_dma_rx_rdy0;if(irqS & FLD_DMA_CHN_UART_RX) //rx{user_uart_que.rx_irq_cnt++;reg_dma_rx_rdy0 = FLD_DMA_CHN_UART_RX;user_uart_que.rx_front = (user_uart_que.rx_front + 1) % USER_MAX_QUE_LEN;if (user_uart_que.rx_rear == user_uart_que.rx_front){user_uart_que.rx_rear = (user_uart_que.rx_rear + 1) % USER_MAX_QUE_LEN;}user_uart_que.p_rx_buf = &user_uart_recv_data[user_uart_que.rx_front];reg_dma0_addr = (u16)((u32)user_uart_que.p_rx_buf);}if(irqS & FLD_DMA_CHN_UART_TX) //tx{user_uart_que.tx_irq_cnt++;reg_dma_rx_rdy0 = FLD_DMA_CHN_UART_TX;}
}
然后就是在主函數(shù)中循環(huán)調(diào)用串口收發(fā)處理函數(shù):
void user_main_loop(void)
{user_rx_from_uart();user_tx_to_uart();
}
在user_app_config.h中補充CB_USER_MAIN_LOOP()宏定義
#define CB_USER_MAIN_LOOP() user_main_loop()
#define CB_USER_INIT() user_app_init()
至此,就可以通過串口收發(fā)自定義數(shù)據(jù)。
如果需要使用串口打印log,可以使用模擬串口,只能發(fā)送,打開HCI_LOG_FW_EN宏,同時定義一下串口的引腳:
#define HCI_LOG_FW_EN 1#if HCI_LOG_FW_EN
#define DEBUG_INFO_TX_PIN GPIO_PC2
#define PRINT_DEBUG_INFO 1
#endif
模擬串口的波特率在myprintf.h中設(shè)置,默認1000000,如果接收到的數(shù)據(jù)亂碼,可以更換串口或者降低波特率。