HAL_UART_Transmit_IT发送数据两次
HAL_UART_Transmit_IT sending data twice
我正在尝试使用 arduino nano 作为中间人在 PC 和 STM32f407-DISC1 板之间建立 UART 通信。
PC 向 arduino 发送 'r' 以指示请求。
然后通过 GPIO 中断将请求传送到 stm32,然后应该使用 HAL_UART_Transmit_IT 传输 480 字节的数据。
然而,它发送了两次数据,只发出了一个请求。
STM32上的代码由STM32CubeMX生成
arduino发出的数据请求
void loop() {
digitalWrite(4, 0); // Clear EXTI11 line.
if (mySerial.available() && received < 480) { // STM32 sending data and is not done.
buff[received] = mySerial.read(); // Append received data to the buffer.
received++;
}
if (received >= 480) { // If the buffer is full
received = 0; // transmit it to PC.
Serial.println(buff);
}
if (Serial.available()) {
if (Serial.read() == 'r') { // PC requests data from the STM32
digitalWrite(4, 1); // Triggers STM32 EXTI11 line.
while (Serial.available()) // Empty the buffer.
Serial.read();
}
}
}
STM32上的数据传输
void EXTI15_10_IRQHandler(void)
{
// Make sure that the interrupt is the good one.
if (HAL_GPIO_ReadPin(data_req_IRQ_GPIO_Port, data_req_IRQ_Pin)) {
if (is_sending_data == FALSE) // If no transmission is happening
should_send_data = TRUE; // raise transmission flag.
}
// IRQ handling stuff...
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef * huart) {
is_sending_data = FALSE; // Transmition is completed, unblock requests.
}
void main(void){
// Init and other stuff...
while (1) {
if (should_send_data == TRUE) { // If data was requested
HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_RESET);
HAL_UART_Transmit_IT(&huart3, matrice, 480); // Start transmission by interrupt.
is_sending_data = TRUE; // Block requests.
should_send_data = FALSE; // Clear flag.
}
// matrice acquisition stuff here
}
}
好吧,我找到了一个解决方案,但这涉及到重新思考我的方法,对于那些正在寻找此问题答案的人来说,我们深表歉意。
我通过用 USB 到 RS232 转换器替换它来删除 arduino 中间人,并通过中断使 UART 接收工作。 STM检测到触发数据通信的'r'字符。
这是中断部分:
void USART3_IRQHandler(void)
{
if (USART3->SR & UART_IT_RXNE) { // If a byte is received
rxBuff[0] = (uint8_t) (huart3.Instance->DR & (uint8_t) 0xFF); // Read it.
__HAL_UART_FLUSH_DRREGISTER(&huart3); // Clear the buffer to avoid errors.
rx_new_char_flag = TRUE; // Raise the new_char flag.
return; // Stops the IRQHandler from disabling interrupts.
}
}
以及主要内容
while (1) {
if (rx_new_char_flag == TRUE) {
rx_new_char_flag = FALSE;
if (rxBuff[0] == 'r') {
rxBuff[0] = 0;
HAL_UART_Transmit_IT(&huart3, matrice, 480); // Start transmission by interrupt.
}
}
在PC端,为了优化性能,我没有等待完整的480字节,而是只等待一个字符,如果收到一个我继续读取串口,如下代码所示
int i = 0;
do {
ReadFile(m_hSerial, &temp_rx[i], 1, &dwBytesRead, NULL);
i++;
} while (dwBytesRead > 0 && i < 480);
for (int j = i; j < 480; j++) // If the transmission is incomplete, fill the buffer with 0s to avoid garbage data.
temp_rx[j] = 0;
if(i>=480) // If all the bytes has been received, copy the data in the working buffer.
std::copy(std::begin(temp_rx), std::end(temp_rx), std::begin(m_touch_state));
这很好用,性能相当不错,所以这可能是我的问题的永久解决方案。
我正在尝试使用 arduino nano 作为中间人在 PC 和 STM32f407-DISC1 板之间建立 UART 通信。 PC 向 arduino 发送 'r' 以指示请求。 然后通过 GPIO 中断将请求传送到 stm32,然后应该使用 HAL_UART_Transmit_IT 传输 480 字节的数据。 然而,它发送了两次数据,只发出了一个请求。
STM32上的代码由STM32CubeMX生成
arduino发出的数据请求
void loop() {
digitalWrite(4, 0); // Clear EXTI11 line.
if (mySerial.available() && received < 480) { // STM32 sending data and is not done.
buff[received] = mySerial.read(); // Append received data to the buffer.
received++;
}
if (received >= 480) { // If the buffer is full
received = 0; // transmit it to PC.
Serial.println(buff);
}
if (Serial.available()) {
if (Serial.read() == 'r') { // PC requests data from the STM32
digitalWrite(4, 1); // Triggers STM32 EXTI11 line.
while (Serial.available()) // Empty the buffer.
Serial.read();
}
}
}
STM32上的数据传输
void EXTI15_10_IRQHandler(void)
{
// Make sure that the interrupt is the good one.
if (HAL_GPIO_ReadPin(data_req_IRQ_GPIO_Port, data_req_IRQ_Pin)) {
if (is_sending_data == FALSE) // If no transmission is happening
should_send_data = TRUE; // raise transmission flag.
}
// IRQ handling stuff...
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef * huart) {
is_sending_data = FALSE; // Transmition is completed, unblock requests.
}
void main(void){
// Init and other stuff...
while (1) {
if (should_send_data == TRUE) { // If data was requested
HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_RESET);
HAL_UART_Transmit_IT(&huart3, matrice, 480); // Start transmission by interrupt.
is_sending_data = TRUE; // Block requests.
should_send_data = FALSE; // Clear flag.
}
// matrice acquisition stuff here
}
}
好吧,我找到了一个解决方案,但这涉及到重新思考我的方法,对于那些正在寻找此问题答案的人来说,我们深表歉意。
我通过用 USB 到 RS232 转换器替换它来删除 arduino 中间人,并通过中断使 UART 接收工作。 STM检测到触发数据通信的'r'字符。 这是中断部分:
void USART3_IRQHandler(void)
{
if (USART3->SR & UART_IT_RXNE) { // If a byte is received
rxBuff[0] = (uint8_t) (huart3.Instance->DR & (uint8_t) 0xFF); // Read it.
__HAL_UART_FLUSH_DRREGISTER(&huart3); // Clear the buffer to avoid errors.
rx_new_char_flag = TRUE; // Raise the new_char flag.
return; // Stops the IRQHandler from disabling interrupts.
}
}
以及主要内容
while (1) {
if (rx_new_char_flag == TRUE) {
rx_new_char_flag = FALSE;
if (rxBuff[0] == 'r') {
rxBuff[0] = 0;
HAL_UART_Transmit_IT(&huart3, matrice, 480); // Start transmission by interrupt.
}
}
在PC端,为了优化性能,我没有等待完整的480字节,而是只等待一个字符,如果收到一个我继续读取串口,如下代码所示
int i = 0;
do {
ReadFile(m_hSerial, &temp_rx[i], 1, &dwBytesRead, NULL);
i++;
} while (dwBytesRead > 0 && i < 480);
for (int j = i; j < 480; j++) // If the transmission is incomplete, fill the buffer with 0s to avoid garbage data.
temp_rx[j] = 0;
if(i>=480) // If all the bytes has been received, copy the data in the working buffer.
std::copy(std::begin(temp_rx), std::end(temp_rx), std::begin(m_touch_state));
这很好用,性能相当不错,所以这可能是我的问题的永久解决方案。