串口输入几个细节问题请求帮助下。
第一次接触嵌入式,看了几天代码,还是稀里糊涂的,不甚清晰。请大神多指教。我的需求: 从串口接收固定长度的字符字节。不是该长度的放弃掉不管。符合长度的处理。下面是我的代码:
//芯片是L496
#include "main.h"
#include <stdint.h>
#define DLen 8 //用长度8测试
//定义了几个函数,写安卓,java,erlang多了,所以大括号习惯请多包涵。
void Start_Recieve(UART_HandleTypeDef *luart);
void ready_next(UART_HandleTypeDef *luart);
HAL_StatusTypeDef Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
int main(void){
UART_HandleTypeDef Lpuart1; //虚拟串口LPUSART1
//一些初始化
HAL_Init();
SystemClock_Config();
LPUART1_Init(&Lpuart1);
LED_Init();
if(HAL_UART_Init(&Lpuart1) == HAL_OK){
HAL_UART_Transmit(&Lpuart1,(uint8_t *)&"\r\nInit ok!\r\n",12,0xffff);
while(1) Start_Recieve(&Lpuart1); //开始接收数据 (问题1????)
}
}
void Start_Recieve(UART_HandleTypeDef *luart){
uint8_t res;
while(HAL_UART_GetState(luart) == HAL_UART_STATE_BUSY_RX){};
if(Receive(luart,res,DLen,2000U) == HAL_OK) //2秒超时,不符合长度的就按照超时不管了。
HAL_UART_Transmit(luart,res,DLen,0xFFFF);//接收到数据的处理函数,就先输出到终端测试了。
ready_next(luart); //处理完,继续等待接收数据
}
//这是接收函数, 从示例代码里面模仿写的。8bit数据, 无校验,1停止
HAL_StatusTypeDef Receive(UART_HandleTypeDef *luart, uint8_t *pData, uint16_t Size, uint32_t Timeout){
uint16_t uhMask;
uint32_t tickstart;
if (huart->RxState == HAL_UART_STATE_READY){
if ((pData == NULL) || (Size == 0U))
returnHAL_ERROR;
__HAL_LOCK(huart);
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->RxState = HAL_UART_STATE_BUSY_RX;
tickstart = HAL_GetTick();
luart->RxXferSize= Size;
luart->RxXferCount = Size;
UART_MASK_COMPUTATION(huart);
uhMask = luart->Mask;
while (luart->RxXferCount > 0U){
if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
return HAL_TIMEOUT;
*pData = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask);
pData++;
luart->RxXferCount--;
}
__HAL_UNLOCK(huart);
return HAL_OK;
}else
return HAL_BUSY;
}
//重新把系统置为等待接收数据状态
void ready_next(UART_HandleTypeDef *luart){
HAL_UART_IRQHandler(luart);
__HAL_UART_ENABLE_IT(luart, UART_IT_RXNE);
luart->RxState = HAL_UART_STATE_READY;
}
上面跑起来没有问题, 测试也正常。有几个疑问解不开:
1. while这样一直搞, 不耗电吗? 有什么好办法,比如唤醒怎么用?
2. 我设置波特率不生效, 现在设置的是115200换成9600就不行了。 要怎么更换呢?
我这样更换不行, huart->Init.BaudRate = 9600U;
3.超长的数据没有找到啥好办法控制。
1、while(1){}这里面的程序是需要重复执行的。唤醒你可以参考一下RTC、STM32休眠与唤醒
2、在上面没有看到你设置波特率的代码,拿我自己的举个例子(HAL库和标准库差不多)
//UART 初始化设置
UART1_Handler.Instance=USART1; //USART1
UART1_Handler.Init.BaudRate=ui32Bound; //波特率
UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B; //字长为8位数据格式
UART1_Handler.Init.StopBits=UART_STOPBITS_1; //一个停止位
UART1_Handler.Init.Parity=UART_PARITY_NONE; //无奇偶校验位
UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE; //无硬件流控
UART1_Handler.Init.Mode=UART_MODE_TX_RX; //收发模式
HAL_UART_Init(&UART1_Handler); //HAL_UART_Init()会使能UART1要更改波特率,更改UART1_Handler.Init.BaudRate=ui32Bound,中的ui32Bound即可。你写的9600U是不对的,就是9600。
3、用串口传输超长的数据,如果你要提速,尤其是对上位机通信,用串口显然是不合适的,建议换usb2.0。
如果是要保证准确率,由于串口一次一般发8bit,如果你的数据是16bit,那么就要对数据进行分割。你可以在每次发送最后设置校验位,对每次发送是否OK,进行校验。
以及,硬件上串口千万不要接线接太长,串口的RX\TX最多接30cm的线,否者误码率会提高不少。
xiaolingoei 发表于 2019-5-3 09:21
1、while(1){}这里面的程序是需要重复执行的。唤醒你可以参考一下RTC、STM32休眠与唤醒
2、在上面没有看 ...
多谢解答。
void LPUART1_Init(UART_HandleTypeDef *huart){
huart->Instance = LPUART1;
huart->Init.BaudRate = 115200U;
huart->Init.WordLength = UART_WORDLENGTH_8B;
huart->Init.StopBits = UART_STOPBITS_1;
huart->Init.Parity = UART_PARITY_NONE;
huart->Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart->Init.Mode = UART_MODE_TX_RX;
huart->Init.OverSampling = UART_OVERSAMPLING_16;
huart->Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_LPUART1_CLK_ENABLE();
//__HAL_UART_ENABLE_IT(huart,UART_IT_RXNE);
GPIO_InitStruct.Pin = GPIO_PIN_7 | GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
}
这是我的初始化配置, 115200就可以, 我修改成9600就不行了,收不到数据。不知道为什么。
超长数据,我的意思是: 如果我就指定接收200字节长的数据。 超过这个长度的我不收, 有办法控制吗? 你代码里面可能是有宏定义?且先撇开LPUART1、115200U这些定义不谈,在配置了UART之后,没有对它进行使能。
你按照这个和你的程序配置比对一下,算是HAL库的标准设置:
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONEBIT_SAMPLING_DISABLED;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
HAL_HalfDuplex_Init(&huart1);
}
这里的接收,是用上位机软件接收还是同样的芯片USART接收?两者通信的波特率一定要匹配,9600就都要设置成9600。
超长数据的处理,我给个思路:你可以__HAL_UART_ENABLE_IT(huart,UART_IT_RXNE); ,在接收中断里面做个计数,接收200次之后关闭USART的接收功能。(PS:不只一种方法)
页:
[1]