我尝试通过Modbus使STM32F103与Eastron SDM630智能电表通信。
在硬件方面,我有中国蓝药片板与STM32F103C8T6。USART1用于与使用中文TTL-RS485转换器模块的智能仪表进行串行通信。信号为5V,但STM32 USART1被映射到可耐受5V的引脚PA9、PA10。PA8用作DE/RE控制引脚(当设置为高电平时启用RS485传输)。波特率是9600。USART3用于USB串行加密狗的调试。
问题是数据传输正常,智能仪表正确并正确响应(用逻辑分析仪检查),但STM32无法接收响应。我在USART1上使用RXNE中断,但看起来ISR永远不会被解雇。
逻辑分析器结果:
代码假设我发送一个Modbus“读取输入寄存器”命令并等待9字节响应(1字节表示slavid,1字节表示命令代码,1字节表示数据响应大小,4字节表示响应,2字节表示CRC16校验和)。
主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 U 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 */
}
美国陆军部
#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生成的。一些注释块(但不是代码!)被删除。
最佳答案
据我所知,您显式启用UART_IT_RXNE
的唯一位置是在RxCallback()
中,而该位置又只能从USART1_IRQHandler()
调用。
很简单,中断从未启用。