我正在学习STM32。我想通过UART逐字节接收数据并中断。
HAL_UART_Receive_IT(&huart1, buffer, length)
&huart1是我的uart门,其中buffer是输入存储,而length是输入字节数。我使用以下功能读取数据
static requestRead(void *buffer, uint16_t length)
{
uint8_t teste;
while (HAL_UART_Receive_IT(&huart1, buffer, length) != HAL_OK) osDelay(1);
//HAL_UART_RxCpltCallback
}
我将数据存储在:
void StartDefaultTask(void const *argument)
{
char sender[] = "Alaska Sending\n";
uint8_t receive[10];
uint8_t data[30];
for (;;)
{
uint8_t i = 0;
memset(data, 0, 30);
requestRead(&receive, 1);
data[i++] = receive;
while (data != '\r')
{
requestRead(&receive, 1);
data[i++] = receive;
}
//HAL_UART_Transmit(&huart1, data, i, HAL_MAX_DELAY);
}
/* USER CODE END StartDefaultTask */
}
我的问题是值的接收和存储。当我通过串行方式发送字符串 Welcome to Alaska \ n (欢迎来到阿拉斯加\ n )时,只读取并存储了W,那么我需要再次发送缓冲区并再次仅存储W。如何解决此问题?>
答案 0 :(得分:0)
好吧,这里有几个问题。
数组及其内容
data[i++] = receive;
将receive
缓冲区的地址(内存指针值)存储到data
数组中。那当然不是你想要的。由于这是一个非常基本的C编程范例,因此建议您回顾一下good C textbook中有关数组和指针的章节。
您发送的内容和期望的内容
while (data != '\r')
即使正确获得数组地址及其值(请参见上文),您也将发送以'\n'
结尾的字符串,并检查一个'\r'
字符,因此请更改一个或其他人来获得比赛。
缺少volatile
uint8_t receive[10];
应将接收缓冲区声明为volatile
,因为它会被中断处理程序访问。否则,即使主程序已经检查了接收是否完成(请参阅下文),也会丢失对缓冲区的写操作。
实时处理硬件
while (HAL_UART_Receive_IT(&huart1, buffer, length) != HAL_OK) osDelay(1);
这将使UART接收(和错误处理)中断能够接收一个字节。到目前为止还可以,但是函数在接收到字节之前返回 ,并且立即再次调用它,它将第二次返回HAL_BUSY
并等待毫秒,然后再尝试。在那毫秒内,它将丢失其余的大部分传输,因为字节到达的速度快于此,并且您的程序对此无能为力。
此外,主程序不检查接收是否完成,可能在中断处理程序将值放入缓冲区之前访问缓冲区。
如果使用中断接收数据,则必须在中断处理程序中对该数据进行某些处理。 (如果您不使用中断,而是使用 polling 进行数据访问,请确保您已达到界面速度所规定的期限)。
HAL不适合此类任务
HAL没有接口来接收以特定值结尾的未知长度的数据。当然,主程序可以一次轮询接收者一个字节,但是它必须确保轮询发生的速度比数据传入的速度快。换句话说,该程序在等待传输时可以做很少的事情。
有一些变通办法,但是我现在什至不予暗示,因为它们会在RTOS环境中导致deadlocks,这往往在最不方便的时间发生,并且很难调查和解决。适当避免。
改为编写您的中断处理程序
(所有详细信息在您的控制器的参考手册中)
NVIC_SetPriority()
NVIC_EnableIRQ()
启用中断USART_CR1_RXNEIE
位设置为1 在中断处理程序中,
SR
寄存器RXNE
位,
别忘了声明将中断处理程序接触的所有变量都声明为volatile
。