寫在前面的話歡迎大家在評論區(qū)指正錯誤,該博文是我在這幾天使用hal庫的時候碰到的問題的記錄,對于暫時沒有寫的像dma、阻塞接收等函數(shù),在后期如果我用道的話,我也會在該博文里面更新。當讓也歡迎大家在評論區(qū)指正。
函數(shù)在這里不介紹關于DMA的操作,只是用有關串口的阻塞和非阻塞函數(shù)。
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
以上4個分別是串口的阻塞接受,發(fā)送和非阻塞的接受和發(fā)送。(關于阻塞和非阻塞,阻塞的過程cpu是需要等待的,而非阻塞的過程相當于中斷)
關于在使用的時候遇到的問題發(fā)送HAL_UART_Transmit在發(fā)送方面,使用HAL_UART_Transmit阻塞數(shù)據(jù)發(fā)送的時候,一定要計算好發(fā)送數(shù)據(jù)的時間。如果發(fā)送時間到了,但是數(shù)據(jù)還沒有發(fā)送完成的話,會導致沒有發(fā)送的數(shù)據(jù)丟失。
HAL_UART_Transmit_IT該函數(shù)是以中斷的方式發(fā)送的數(shù)據(jù),是非阻塞的。在使用的時候,可以寫成類似printf的函數(shù)。在這里我參照的是正點原子庫函數(shù)版本改過來的。
void u2_printf(char *str,...)
{
uint16_t j;
va_list ap;
va_start(ap,str);
vsprintf((char*)USART2_T_M,str,ap);
va_end(ap);
HAL_UART_Transmit_IT(&huart2,(uint8_t *)USART2_T_M,strlen((const char*)USART2_T_M));
}
但是該函數(shù)還存在問題,在字符串中默認0x00是一個字符串的接受。所以自己寫的這種類printf的函數(shù)并不能在字符串中間加入0x00進行數(shù)據(jù)發(fā)送。(0x00一般在某些模塊的數(shù)據(jù)通信中會使用到)但是使用半主機模式下的printf函數(shù)可以解決該問題。
使用printf函數(shù)這一部分代碼我參照的是正點原子的給出的代碼,直接改過來使用的。使用的是半主機模式下的printf函數(shù)。
#if 1
#pragma import(__use_no_semihosting)
//標準庫需要的支持函數(shù)
struct __FILE
{
int handle;
};
FILE __stdout;
//定義_sys_exit()以避免使用半主機模式
void _sys_exit(int x)
{
x = x;
}
//重定義fputc函數(shù)
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//循環(huán)發(fā)送,直到發(fā)送完畢
USART1->DR = (uint8_t) ch;
return ch;
}
#endif
在這里面,通過更改USART1修改映射串口。
接收阻塞模式下的接收函數(shù)沒有測試過,就不在這里寫了。以后有機會用到了,會進行添加。
HAL_UART_Receive_IT使用中斷的方式進行接受數(shù)據(jù),在這里需要注意的一個點是,使用中斷的方式接收到數(shù)據(jù)之后,需要在中斷里面在調用一次HAL_UART_Receive_IT函數(shù),重新開啟下一次數(shù)據(jù)接收,否則會導致,接收完一次數(shù)據(jù)之后,不會接收下一次數(shù)據(jù)。
HAL_UART_Receive_IT(&huart2,&usart2_rdata,1);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2) //串口屏,接收中斷
{
HAL_UART_Receive_IT(&huart2,&usart2_rdata,1);
}
}
在這里我是用的是,接收一個字符后就會觸發(fā)一次中斷。當然也可以一次接收多個字符數(shù)據(jù)。