串行接口是指數(shù)據(jù)一位一位地順序傳送,其特點(diǎn)是通信線路簡(jiǎn)單,只要一對(duì)傳輸線就可以實(shí)現(xiàn)雙向通信(可以直接利用電話線作為傳輸線)榄融,從而大大降低了成本,特別適用于遠(yuǎn)距離通信救湖,但傳送速度較慢愧杯。一條信息的各位數(shù)據(jù)被逐位按順序傳送的通訊方式稱為串行通訊。串行通訊的特點(diǎn)是:數(shù)據(jù)位的傳送鞋既,按位順序進(jìn)行力九,最少只需一根傳輸線即可完成;成本低但傳送速度慢邑闺。串行通訊的距離可以從幾米到幾千米跌前;根據(jù)信息的傳送方向,串行通訊可以進(jìn)一步分為單工陡舅、半雙工和全雙工三種抵乓。來(lái)自百度百科
STM32 的串口資源相當(dāng)豐富的,功能也相當(dāng)強(qiáng)勁。
串口服務(wù)靶衍,當(dāng)串口有數(shù)據(jù)要接收時(shí)灾炭,MCU產(chǎn)生中斷將串口中的數(shù)據(jù)讀入。現(xiàn)將串口的服務(wù)程序?qū)崿F(xiàn)如下:
- 串口隊(duì)列颅眶,當(dāng)MCU有數(shù)據(jù)讀入時(shí)蜈出,將MCU的數(shù)據(jù)讀入串口隊(duì)列中;
- 串口服務(wù)程序在while主循環(huán)中涛酗,若串口隊(duì)列中有數(shù)據(jù)铡原,將數(shù)據(jù)讀入到串口接收緩存內(nèi)。
- 當(dāng)串口接收緩存內(nèi)的數(shù)據(jù)達(dá)到了自定義數(shù)據(jù)的一幀煤杀,則進(jìn)行后續(xù)的數(shù)據(jù)處理眷蜈。
串口隊(duì)列(uart_queue_buf):一個(gè)隊(duì)列沪哺,每當(dāng)發(fā)生串口中斷時(shí)沈自,在串口中接受的數(shù)據(jù)放入這個(gè)隊(duì)列中。
queue_head:隊(duì)列頭指針辜妓,當(dāng)串口服務(wù)程序從這個(gè)隊(duì)列中讀取數(shù)據(jù)時(shí)的開始位置枯途。
queue_tail:隊(duì)列尾指針,隊(duì)列數(shù)據(jù)的截止位置籍滴。
queue_total_data_length:隊(duì)列中有效數(shù)據(jù)的總長(zhǎng)度酪夷。
串口接收緩存(uart_rx_buf):串口服務(wù)程序從串口隊(duì)列中讀取到數(shù)據(jù)放到這個(gè)接收緩存中,進(jìn)行數(shù)據(jù)解析孽惰。
串口發(fā)送緩存(uart_tx_buf):將需要發(fā)生的數(shù)據(jù)放入發(fā)送緩存晚岭,調(diào)用發(fā)送接口將數(shù)據(jù)發(fā)送到串口。
串口中斷讀取串口數(shù)據(jù)到串口隊(duì)列
void USART1_IRQHandler(void)
{
uint8_t data;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
data = USART_ReceiveData(USART1);
// 接收串口的數(shù)據(jù)
uart_receive_input(data);
USART_ClearFlag(USART1,USART_FLAG_RXNE);
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
串口數(shù)據(jù)接收函數(shù)
void uart_receive_input(unsigned char value)
{
//隊(duì)列不滿
if(queue_total_data < sizeof(uart_queue_buf) {
if(queue_head >= (unsigned char *)(uart_queue_buf + sizeof(uart_queue_buf))) {
queue_head = (unsigned char *)(uart_queue_buf);
}
*queue_head ++ = value;
queue_total_data ++;
} else {
//數(shù)據(jù)隊(duì)列滿
}
}
獲取隊(duì)列內(nèi)數(shù)據(jù)的總長(zhǎng)度
unsigned short get_uart_queue_total_length(void)
{
return queue_total_data_length;
}
讀取隊(duì)列1字節(jié)數(shù)據(jù)
unsigned char queue_read_byte(void)
{
unsigned char value = 0;
// 串口隊(duì)列緩存內(nèi)有數(shù)據(jù)
if (queue_total_data_length > 0) {
if (queue_tail >= (unsigned char *) (uart_queue_buf + sizeof(uart_queue_buf))) {
//數(shù)據(jù)已經(jīng)到末尾勋功,將尾指針指向頭
queue_tail = (unsigned char *) (uart_queue_buf);
}
value = *queue_tail++;
queue_total_data_length--;
}
return value;
}
串口服務(wù)程序(請(qǐng)將此函數(shù)放到while的主循環(huán)里)
void uart_service()
{
// 當(dāng)隊(duì)列內(nèi)有數(shù)據(jù)時(shí)坦报,讀取隊(duì)列內(nèi)的所有數(shù)據(jù)
while((rx_in < sizeof(uart_rx_buf)) && get_uart_queue_total_data() > 0) {
uart_rx_buf[rx_in ++] = queue_read_byte();
}
// 串口數(shù)據(jù)處理(此處內(nèi)的函數(shù)由作者自己實(shí)現(xiàn))
uart_data_handle(offset);
// 注意處理完后库说,請(qǐng)?jiān)谶@個(gè)位置將已經(jīng)處理過的數(shù)據(jù)刪除(可以使用memcpy內(nèi)存拷貝將后面需要處理的數(shù)據(jù)拷貝到緩存區(qū)開始)
}