简体   繁体   English

STM32F103在RX中断时无法通过UART接收数据

[英]STM32F103 Cannot receive data via UART on RX interrupt

I try to make STM32F103 communicate with Eastron SDM630 smart meter via Modbus. 我试图使STM32F103通过Modbus与Eastron SDM630智能电表通信。

On the hardware side I have chinese BluePill board with STM32F103C8T6. 在硬件方面,我有带STM32F103C8T6的中文BluePill板。 USART1 is used for serial comms with smart meter using the chinese TTL-RS485 converter module. USART1用于使用中文TTL-RS485转换器模块的智能电表的串行通信。 The signals are 5V but STM32 USART1 is mapped to pins PA9, PA10 that are 5V tolerant. 信号为5V,但STM32 USART1映射到5V耐压的引脚PA9,PA10。 PA8 is used as the DE/RE control pin (enables RS485 transmission whel set to high level). PA8用作DE / RE控制引脚(使RS485传输线设置为高电平)。 Baudrate is 9600. USART3 is used for debug with USB-serial dongle. 波特率为9600。USART3用于通过USB串行加密狗进行调试。

The problem is that data is being transferred OK and smart meter gets it right and responds correctly (checked it with logic analyzer) but STM32 cannot receive the response. 问题在于数据可以正常传输,并且智能电表可以正确并正确响应(通过逻辑分析仪检查),但是STM32无法接收到响应。 I use RXNE interrupt on USART1 but it looks like the ISR never get fired. 我在USART1上使用RXNE中断,但看起来ISR从未触发。

Logic analyzer results: 逻辑分析仪结果: 逻辑分析仪结果

The code assumes that I send a Modbus "Read input register" command and wait for 9-byte response (1byte for slaveID, 1byte for command code, 1byte for data response size, 4bytes of response and 2bytes of CRC16 checksum). 该代码假定我发送了一个Modbus“读取输入寄存器”命令,并等待9字节响应(slaveID为1字节,命令代码为1字节,数据响应大小为1字节,数据响应为4字节,CRC16校验和为2字节)。

main.c main.c

#include "main.h"
#include "gpio.h"
#include "stm32f1xx_hal.h"
#include "usart.h"
#include <string.h>
#include "crc16.h"
#include "word.h"

uint8_t buffer[256];
uint8_t cmd[256];
uint8_t cmdCounter = 0;
volatile uint8_t response[255];
volatile uint8_t responseCounter = 0;
volatile uint8_t rxComplete = 0;
uint8_t estimatedCounter = 0;
uint16_t crc = 0xFFFF;


void SystemClock_Config(void);
void CycleComplete(void);
void SerialPrint(UART_HandleTypeDef *usart, uint8_t *buffer, int n);.
void RXCallback(void);


void SerialPrint(UART_HandleTypeDef *usart, uint8_t *buffer, int n)
{
    HAL_UART_Transmit(usart, (uint8_t *)buffer, n, 100);
}

void RXCallback()
{
    response[responseCounter] = (uint8_t)(USART1->DR & 0x00FF);
    if(responseCounter == estimatedCounter)
    {
        CycleComplete();
    }
    else
    {
        __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);
        responseCounter++;
    }
}

void CycleComplete()
{
    int n;
    n = sprintf((char*)buffer, "Received %d bytes\n", responseCounter);
    SerialPrint(&huart3, buffer, n);

    n = sprintf((char*)buffer, "Response: 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", response[0], response[1], response[2], response[3], response[4], response[5], response[6], response[7], response[8]);
    SerialPrint(&huart3, buffer, n);

    crc = 0xFFFF;
    rxComplete = 1;
}

int main(void)
{
    HAL_Init();
    SystemClock_Config();

    MX_GPIO_Init();
    MX_USART1_UART_Init();
    MX_USART3_UART_Init();

    int n = sprintf((char *)buffer, "Starting up...\n");
    SerialPrint(&huart3, buffer, n);

    while (1)
    {
        cmdCounter = 0;
        cmd[0] = 0x01;
        cmd[1] = 0x04;
        cmd[2] = 0x00;
        cmd[3] = 0x00;
        cmd[4] = 0x00;
        cmd[5] = 0x02;
        for(int a = 0; a <= 5; a++)
        {
            crc = crc16_update(crc, cmd[a]);
        }
        cmd[6] = lowByte(crc);
        cmd[7] = highByte(crc);

        estimatedCounter = 9; // slaveID + opCode + no.of bytes + 4 bytes of data + 2 bytes of CRC16

        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
        SerialPrint(&huart1, cmd, 8);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);

        while(rxComplete != 1){};
        rxComplete = 0;

        HAL_Delay(3000);
    }
}


void SystemClock_Config(void)
{

    RCC_OscInitTypeDef RCC_OscInitStruct;
    RCC_ClkInitTypeDef RCC_ClkInitStruct;

    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.HSICalibrationValue = 16;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        _Error_Handler(__FILE__, __LINE__);
    }

    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
    {
        _Error_Handler(__FILE__, __LINE__);
    }

    HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000);
    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
    HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

stm32f1xx_it.c stm32f1xx_it.c

#include "stm32f1xx_it.h"
#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
#include "main.h"

extern UART_HandleTypeDef huart1;

void NMI_Handler(void)
{
}

void HardFault_Handler(void)
{
    while (1)
    {
    }
}

void MemManage_Handler(void)
{
    while (1)
    {
    }
}

void BusFault_Handler(void)
{
    while (1)
    {
    }
}

void UsageFault_Handler(void)
{
    while (1)
    {
    }
}

void SVC_Handler(void)
{
}

void DebugMon_Handler(void)
{
}

void PendSV_Handler(void)
{
}

void SysTick_Handler(void)
{
    HAL_IncTick();
    HAL_SYSTICK_IRQHandler();
}


void USART1_IRQHandler(void)
{
    /* USER CODE BEGIN USART1_IRQn 0 */
    if(__HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_RXNE) != RESET)
    {
        RXCallback();
    }
    HAL_NVIC_ClearPendingIRQ(USART1_IRQn);
    /* USER CODE END USART1_IRQn 0 */
    HAL_UART_IRQHandler(&huart1);
    /* USER CODE BEGIN USART1_IRQn 1 */

    /* USER CODE END USART1_IRQn 1 */
}

usart.c usart.c

#include "usart.h"
#include "gpio.h"

UART_HandleTypeDef huart1;
UART_HandleTypeDef huart3;

void MX_USART1_UART_Init(void)
{
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 9600;
    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;
    if (HAL_UART_Init(&huart1) != HAL_OK)
    {
        _Error_Handler(__FILE__, __LINE__);
    }
}

void MX_USART3_UART_Init(void)
{
    huart3.Instance = USART3;
    huart3.Init.BaudRate = 115200;
    huart3.Init.WordLength = UART_WORDLENGTH_8B;
    huart3.Init.StopBits = UART_STOPBITS_1;
    huart3.Init.Parity = UART_PARITY_NONE;
    huart3.Init.Mode = UART_MODE_TX_RX;
    huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart3.Init.OverSampling = UART_OVERSAMPLING_16;
    if (HAL_UART_Init(&huart3) != HAL_OK)
    {
        _Error_Handler(__FILE__, __LINE__);
    }
}

void HAL_UART_MspInit(UART_HandleTypeDef *uartHandle)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    if (uartHandle->Instance == USART1)
    {
        __HAL_RCC_USART1_CLK_ENABLE();

        GPIO_InitStruct.Pin = GPIO_PIN_9;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_10;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(USART1_IRQn);
    }
    else if (uartHandle->Instance == USART3)
    {
        __HAL_RCC_USART3_CLK_ENABLE();

        GPIO_InitStruct.Pin = GPIO_PIN_10;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_11;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef *uartHandle)
{
    if (uartHandle->Instance == USART1)
    {
        __HAL_RCC_USART1_CLK_DISABLE();

        HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9 | GPIO_PIN_10);

        HAL_NVIC_DisableIRQ(USART1_IRQn);
    }
    else if (uartHandle->Instance == USART3)
    {
        __HAL_RCC_USART3_CLK_DISABLE();
        HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10 | GPIO_PIN_11);
    }
}

gpio.c gpio

#include "gpio.h"

void MX_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();

    /*Configure GPIO pin Output Level */
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);

    /*Configure GPIO pin Output Level */
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);

    /*Configure GPIO pin : PC13 */
    GPIO_InitStruct.Pin = GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    /*Configure GPIO pin : PA8 */
    GPIO_InitStruct.Pin = GPIO_PIN_8;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

The code is generated with CubeMX. 该代码是使用CubeMX生成的。 Some comment blocks (but NOT code!) are deleted. 一些注释块(但不是代码!)被删除。

As far as I can determine, the only place you explicitly enable UART_IT_RXNE is in RxCallback() which in turn is only ever called from USART1_IRQHandler() . 据我所知,唯一显式启用UART_IT_RXNERxCallback() ,而后者只能从USART1_IRQHandler()调用。

Quite simply the interrupt is never enabled. 非常简单,永远不会启用中断。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM