能帮我解释下PC机通过rs485串口接收智能电表的数据,具体过程是怎样实现的,谢谢

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了能帮我解释下PC机通过rs485串口接收智能电表的数据,具体过程是怎样实现的,谢谢相关的知识,希望对你有一定的参考价值。

分两个过程
第一是物理线路连接好以后,安装底层通讯协议,实现通讯,也就是大家说的安装驱动程序,没安装好没办法通讯,简单的说就是统一一个语言标准,不然电表读不懂PC发送的数据,PC也读不懂电表返回的数据。(驱动程序在电表厂家有,或者拆开表,看了内部结构和芯片型号高手也能编译得出来,公网上冒是没得下的,嘿嘿。。。。)
第二在安装好驱动程序以后,应用层面得有一个操作软件来对电表内数据进行读写,这个厂家有,公网上应该也有可以下载的。
(PS:如果你是想对电表进行研究,这里有个思路,提供你参考。现在的智能电表内有块芯片,叫计数累加器,在采样读取N千次以后向主芯片提供一次电信号,记录一度电,比如原设计采样1000次记录1度电,人工更换一款累加器芯片,则变成采样4000次记录1度电,那么电表记录的用电量将变成实际用电量的四分之一,反之则变成四倍。当然,提供这些方法只是扩展大家对电子技术方面兴趣,并非为了方便某些人进行违法活动)追问

我看了645多功能电表通信协议,要给智能电表发送命令后,才有返回数据,现在的问题是不知道怎样把命令加到程序中

追答

你的那个通信协议软件能找到智能电表吗?
哎,和你简单描叙下吧,RS485通讯协议在现有的电子产品中应用分为两个层面:
第一是 管理机------执行部件之间,比如监控产品的 主机 对 前端云台的控制就属于这种方式,管理机发送代码,执行部件只负责按照代码的要求进行动作。
第二是 管理机------终端机之间,你想了解的就是这种连接方式的。因为终端机是一个独立的单片机系统,当终端机接收到一段代码以后,会根据原厂设定的编码进行解码,该代码是否能被终端机读懂?读懂了以后,依据原厂设定的权限,终端机是否会按照代码的要求进行执行?这些都是需要解决的问题。所以了解终端机的编解码方式,其权限设定都是很重要的。
依据这个思路,你连接好PC和智能电表后,PC发现不了智能电表(不装驱动程序),就说明他们之间没有进行统一编解码,即使用的是明文方式,你就确定发送编码过去,没获取操作权限,电表一定会鸟你?
至于你说的,不知道怎么把命令加到程序中,你是想按照自己的思路开发呢还是现有一套窗口化的软件不知道怎么用。没明白你的意思。

参考技术A 一 首先电脑要有rs485串口,现在PC机有这种接口的很少了
二 要设置rs485串口传输协议。
参考技术B 通信协议 是 modbus 吧

电脑发送 指令,等电表返回数据追问

在软件里怎么实现智能电表通过rs485串口自动发送数据啊?谢谢

参考技术C 也想知道。

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

我尝试通过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
", 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
", 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...
");
    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生成的。删除了一些注释块(但不是代码!)。

答案

据我所知,唯一明确启用UART_IT_RXNE的地方是RxCallback(),而USART1_IRQHandler()只能从qazxswpoi调用。

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

以上是关于能帮我解释下PC机通过rs485串口接收智能电表的数据,具体过程是怎样实现的,谢谢的主要内容,如果未能解决你的问题,请参考以下文章

如何用电脑读取485接口的电表数据

电脑和USB和RS485和电表怎么连接

红外接口转RS485接口技术方案--红外抄表转换器用于智能电表非接触抄表采集

如何在电脑上通过RS485接口读取PMC-630A三相数字式多功能测控电表。最好能写上详细过程。功能码为0x03.

普通PC通过USB转485串口 ModBus-RTU通信协议控制伺服电机

电脑读取RS485接口电表 软件