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

时间:2018-03-03 16:18:55

标签: c embedded stm32 modbus

我尝试通过Modbus使STM32F103与Eastron SDM630智能电表通信。

在硬件方面,我有中文BluePill板和STM32F103C8T6。 USART1用于使用中国TTL-RS485转换器模块的智能电表的串行通信。信号为5V,但STM32 USART1映射到5V耐压的引脚PA9,PA10。 PA8用作DE / RE控制引脚(使RS485变速器设置为高电平)。波特率为9600. USART3用于USB串行加密狗调试。

问题是数据传输正常,智能电表正确并正确响应(用逻辑分析仪检查)但STM32无法接收响应。我在USART1上使用RXNE中断,但看起来ISR永远不会被解雇。

逻辑分析仪结果: Logic analyzer results

代码假定我发送Modbus“读取输入寄存器”命令并等待9字节响应(slaveID为1byte,命令代码为1byte,数据响应大小为1byte,响应为4bytes,CRC16校验和为2bytes)。

的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

#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

#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

#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);
}

代码是使用CubeMX生成的。删除了一些注释块(但不是代码!)。

1 个答案:

答案 0 :(得分:2)

据我所知,明确启用UART_IT_RXNE的唯一位置是RxCallback(),而USART1_IRQHandler()只能从{{1}}调用。

很简单,中断永远不会启用。