當前位置:首頁 > 公眾號精選 > 嵌入式云IOT技術圈
[導讀]之前買了一塊評估板,也寫了相應的評測文章,鏈接如下: TKM32F499高性能MCU評估板試用之萬事開頭難,先點個燈來壓壓驚! 我們在上面這篇文章已經(jīng)領會了TKM32F499的強大了,接下來進入主題,串口通信實驗。 1、TKM32F499通用異步收發(fā)器(UART)數(shù)據(jù)結構及參數(shù)描

之前買了一塊評估板,也寫了相應的評測文章,鏈接如下:

TKM32F499高性能MCU評估板試用之萬事開頭難,先點個燈來壓壓驚!

我們在上面這篇文章已經(jīng)領會了TKM32F499的強大了,接下來進入主題,串口通信實驗。

1、TKM32F499通用異步收發(fā)器(UART)數(shù)據(jù)結構及參數(shù)描述

在UART庫的頭文件里,UART由一個結構體進行維護:

typedef struct
{
//波特率
uint32_t UART_BaudRate;
//數(shù)據(jù)長度
uint16_t UART_WordLength;
//停止位
uint16_t UART_StopBits;
//校驗位
uint16_t UART_Parity;
//模式
uint16_t UART_Mode;
//硬件流控
uint16_t UART_HardwareFlowControl;
} UART_InitTypeDef;

1.1 波特率

波特率是由波特率發(fā)生器產(chǎn)生的,這是一個專用16位的,UART波特率寄存器控制16 位自由運轉(zhuǎn)的計數(shù)器的計數(shù)周期。提供期望的波特率和 Fosc(APB 時鐘頻率)

X = SPBRG 寄存器值 (1 to 65535)


1.2 數(shù)據(jù)長度

/** @defgroup UART_Word_Length
* @{
*/
#define UART_WordLength_5b ((uint16_t)0x0000)
#define UART_WordLength_6b ((uint16_t)0x0010)
#define UART_WordLength_7b ((uint16_t)0x0020)
#define UART_WordLength_8b ((uint16_t)0x0030)

一般在工程應用中都是選擇UART_WordLength_8b

1.3 停止位

/** @defgroup UART_Stop_Bits
* @{
*/

#define UART_StopBits_1 ((uint16_t)0x0000)
#define UART_StopBits_2 ((uint16_t)0x0004)

#define IS_UART_STOPBITS(STOPBITS) (((STOPBITS) == UART_StopBits_1) || \
((STOPBITS) == UART_StopBits_2))

一般在工程應用中都是選擇UART_StopBits_1

1.4 校驗位

/** @defgroup UART_Parity
* @{
*/
#define UART_Parity_No ((uint16_t)0x0000)
#define UART_Parity_Even ((uint16_t)0x0003)
#define UART_Parity_Odd ((uint16_t)0x0001)
#define IS_UART_PARITY(PARITY) (((PARITY) == UART_Parity_No) || \
((PARITY) == UART_Parity_Even) || \
((PARITY) == UART_Parity_Odd))

一般在工程應用中都是選擇UART_Parity_No(無校驗)

1.5 串口模式

/** @defgroup UART_Mode
* @{
*/

#define UART_Mode_Rx ((uint16_t)0x0008)
#define UART_Mode_Tx ((uint16_t)0x0010)
#define IS_UART_MODE(MODE) ((((MODE) & (uint16_t)0xFFE7) == 0x00) && ((MODE) != (uint16_t)0x00))

這個指的是當前串口為可接收還是可發(fā)送,可以同時擁有,也可以單個選擇,具體根據(jù)項目需求制定。

1.6 硬件流控

/** @defgroup UART_Hardware_Flow_Control
* @{
*/
#define UART_HardwareFlowControl_None ((uint16_t)0x0000)

#define IS_UART_HARDWARE_FLOW_CONTROL(CONTROL)\
(((CONTROL) == UART_HardwareFlowControl_None) || \
((CONTROL) == UART_HardwareFlowControl_RTS) || \
((CONTROL) == UART_HardwareFlowControl_CTS) || \
((CONTROL) == UART_HardwareFlowControl_RTS_CTS))

一般工程應用中會直接將這個設置為UART_HardwareFlowControl_None 在HAL_uart.h庫文件中提供了一系列操作接口:

void UART_DeInit(UART_TypeDef* UARTx);
void UART_Init(UART_TypeDef* UARTx, UART_InitTypeDef* UART_InitStruct);
void UART_StructInit(UART_InitTypeDef* UART_InitStruct);
void UART_Cmd(UART_TypeDef* UARTx, FunctionalState NewState);
void UART_ITConfig(UART_TypeDef* UARTx, uint16_t UART_IT, FunctionalState NewState);
void UART_DMACmd(UART_TypeDef* UARTx, uint16_t UART_DMAReq, FunctionalState NewState);
void UART_SendData(UART_TypeDef* UARTx, uint16_t Data);
uint16_t UART_ReceiveData(UART_TypeDef* UARTx);
FlagStatus UART_GetFlagStatus(UART_TypeDef* UARTx, uint16_t UART_FLAG);
void UART_ClearFlag(UART_TypeDef* UARTx, uint16_t UART_FLAG);
ITStatus UART_GetITStatus(UART_TypeDef* UARTx, uint16_t UART_IT);
void UART_ClearITPendingBit(UART_TypeDef* UARTx, uint16_t UART_IT);

跟STM32操作類似,我們直接調(diào)就完了,不明白的地方直接看數(shù)據(jù)手冊解決!

2、TKM32F499通用異步收發(fā)器(UART)使用

使用串口功能之前,還是一樣,先確定我這邊的需求,我這邊需要接收一串以下格式的數(shù)據(jù):

序號 信號值 差值\r\n

這個數(shù)據(jù)是我手上傳感器發(fā)過來的數(shù)據(jù),然后我用TKM32F499進行接收。

1、配置一路串口用于printf輸出,這里選擇UART4

電路原理圖如下:

根據(jù)原理圖寫出以下初始化函數(shù):

/*用于調(diào)試打印*/
void Uart4Init(int BaudRate)
{
UART_InitTypeDef UART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 復用推挽輸出
GPIO_Init(GPIOD, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉輸入

GPIO_Init(GPIOD, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOD, GPIO_Pin_6 | GPIO_Pin_7, GPIO_AF_UART_2345);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART4, ENABLE);
UART_InitStructure.UART_BaudRate = BaudRate; //波特率
UART_InitStructure.UART_WordLength = UART_WordLength_8b;//數(shù)據(jù)位
UART_InitStructure.UART_StopBits = UART_StopBits_1;//停止位
UART_InitStructure.UART_Parity = UART_Parity_No ;
UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx;//輸入輸出模式
UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
UART_Init(UART4, &UART_InitStructure);
UART_Cmd(UART4, ENABLE); //UART 模塊使能

UART_ClearITPendingBit(UART4, 0xff);
}

調(diào)試不用增加接收功能,所以不需要寫接收回調(diào)函數(shù),但需要寫一個串口重定向,并把微庫勾上才能使用printf。

編寫重定向函數(shù):

int fputc(int ch, FILE *f)
{
while((UART4->CSR & 0x1) == 0) {}
UART4->TDR = (u8) ch;
return ch;
}

2、配置一路串口用于接收傳感器數(shù)據(jù)(這里選擇接UART1)

電路原理圖如下:

實現(xiàn)代碼邏輯:

/*用于接收傳感器數(shù)據(jù)*/
void Uart1Init(int BaudRate)
{
UART_InitTypeDef UART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //uart1_tx pa9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 推挽復用輸出
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //uart1_rx pa10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉輸入

GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOA, GPIO_Pin_9 | GPIO_Pin_10, GPIO_AF_UART_1); //PA9、PA10復用為串口1
GPIO_PinAFConfig(GPIOA, GPIO_Pin_15, GPIO_AF_GPIO); //PA15復用為普通GPIO

RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1, ENABLE);
UART_InitStructure.UART_BaudRate = BaudRate; //波特率
UART_InitStructure.UART_WordLength = UART_WordLength_8b;//數(shù)據(jù)位
UART_InitStructure.UART_StopBits = UART_StopBits_1;//停止位
UART_InitStructure.UART_Parity = UART_Parity_No ;
UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx;//輸入輸出模式
UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
UART_Init(UART1, &UART_InitStructure);
UART_Cmd(UART1, ENABLE); //UART 模塊使能

UART_ClearITPendingBit(UART1, 0xff);
//這里需要進行接收,所以要打開接收中斷
UART_ITConfig(UART1, UART_IT_RXIEN, ENABLE);//使能接收中斷
NVIC_SetPriority(UART1_IRQn, 3);
NVIC_EnableIRQ(UART1_IRQn);
}

定義回調(diào)函數(shù),編寫接收邏輯,傳感器用一個結構體進行維護:

#define SENSOR_BUFFER_SIZE       42

typedef struct
{
uint8_t BufferReady;
uint16_t Sensor_rx_count ;
uint8_t SensorRxBuffer[SENSOR_BUFFER_SIZE];
uint8_t SensorTxBuffer[SENSOR_BUFFER_SIZE];
} Sensor_HandleTypeDef;
extern Sensor_HandleTypeDef Sensor;

接收回調(diào)函數(shù)處理:

//串口1接收中斷處理函數(shù),打印傳感器數(shù)據(jù)
void UART1_IRQHandler(void)
{
u8 ucCh;

/*當ISR位1為1時,表示接收到有效字節(jié)數(shù)據(jù)*/
if(UART1->ISR & (1 << 1))
{
/*接收到了一個字節(jié)的數(shù)據(jù)*/
ucCh = UART1->RDR;
if('\n' != ucCh)
{
Sensor.SensorRxBuffer[Sensor.Sensor_rx_count++] = ucCh ;
}
else
{
/*如果接收的是\n,則上一個接收的數(shù)據(jù)為'\r'結束*/
if('\r' == Sensor.SensorRxBuffer[Sensor.Sensor_rx_count - 1])
{
/*添加結束符*/
Sensor.SensorRxBuffer[Sensor.Sensor_rx_count - 1] = 0x00 ;
/*接收計數(shù)清0*/
Sensor.Sensor_rx_count = 0 ;
Sensor.BufferReady = 1 ;
}
}
/*清除中斷接收標志*/
UART1->ICR |= 1 << 1;
}
}

接收這里主要用到串口的接收數(shù)據(jù)寄存器、中斷狀態(tài)寄存器、中斷清除寄存器

接收數(shù)據(jù)在程序里就是一個RDR的寄存器。其中在接收邏輯里需要去判斷接收數(shù)據(jù)有效,最重要的是位1:

在每次收到一次有效數(shù)據(jù),即發(fā)生了一次串口接收中斷,我們接收完數(shù)據(jù)后需要及時對中斷標志進行清除,這里最重要的是第一位:這些寄存器都是通過一個結構體進行維護:

/**
* @brief Universal Synchronous Asynchronous Receiver Transmitter
*/

typedef struct
{
__IO uint32_t TDR;
__IO uint32_t RDR;
__IO uint32_t CSR;
__IO uint32_t ISR;
__IO uint32_t IER;
__IO uint32_t ICR;
__IO uint32_t GCR;
__IO uint32_t CCR;
__IO uint32_t BRR;
__IO uint32_t FRABRG;

} UART_TypeDef;

具體使用方法請參考TKM32F499的芯片數(shù)據(jù)手冊,當然如果不習慣用寄存器進行操作,也可以使用好炬潤官方的HAL lib,調(diào)用相應的庫函數(shù)。串口應用邏輯編寫完畢以后,接下來我們在主函數(shù)的循環(huán)內(nèi)判斷BufferReady標志就可以了:

while(1)
{
if(1 == Sensor.BufferReady)
{
Sensor.BufferReady = 0;
/*解析傳感器數(shù)據(jù)*/
Sensor_Detect_Process(Sensor.SensorRxBuffer);
printf("流水號:%d 信號值:%d 差值:%d\n",sensor_data.Sensor_Serial_Number
,sensor_data.Sensor_TP1_Singal_Value,sensor_data.Sensor_TP1_Devalue
);
LCD_PutString(100, 60, (char *)Sensor.SensorRxBuffer, Red, Yellow, 1);
status = !status;
GPIO_WriteBit(GPIOA,GPIO_Pin_15,status);
}
}

最終效果,這里面還有我的其它邏輯:

如果對該評估板軟件編程感興趣的話,歡迎加我微信私聊交流~

TKM32F499評估板例程及資料下載

鏈接:https://pan.baidu.com/s/1xujEO4vJ7i7UUK7v_fGNgw
提取碼:g1y2

或者后臺回復TK499即可獲取。

往期精彩

bin文件轉(zhuǎn)換為hex文件C語言實現(xiàn)

最近收集的開源項目專欄(持續(xù)更新,收好車輪,方便造車)

推薦三個我工作中經(jīng)常使用的驅(qū)動大全wiki(建議收藏并轉(zhuǎn)發(fā)讓更多人知道!)

變量命名還在谷歌百度翻譯?OUT啦!分享一個我日常工作中常用的變量命名神器!

若覺得本次分享的文章對您有幫助,隨手點[在看]并轉(zhuǎn)發(fā)分享,也是對我的支持。

免責聲明:本文內(nèi)容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉