由于题目中没有明确的要求,以下是一个简单的示例程序,实现了一个基本的MBus电表从机功能。该程序使用STM32F103作为主控芯片,使用Keil MDK-ARM作为开发环境。

程序包含以下功能:

  1. 通过USART1与主控通信,收到主控发送的MBus命令后,解析命令并回复对应的应答数据。
  2. 实现了MBus协议中的数据帧解析和校验功能。
  3. 通过GPIO控制LED灯,用于表示程序运行状态。

程序中使用了STM32的库函数,具体实现可以参考官方文档或其他教程。

代码如下:

#include "stm32f10x.h"
#include <stdio.h>
#include <string.h>

#define BUF_SIZE 64
#define LED_PIN GPIO_Pin_13
#define LED_PORT GPIOC

typedef enum {
    STATE_WAIT_START,
    STATE_WAIT_C,
    STATE_WAIT_L,
    STATE_WAIT_DATA,
    STATE_WAIT_CRC,
    STATE_WAIT_STOP
} MbusState;

uint8_t g_buf[BUF_SIZE];
uint8_t g_buf_len;
MbusState g_state;

void USART1_Init(void);
void GPIO_Init(void);
void LED_On(void);
void LED_Off(void);
void MBus_Process(void);

int main(void)
{
    USART1_Init();
    GPIO_Init();
    g_state = STATE_WAIT_START;
    while (1) {
        MBus_Process();
    }
}

void USART1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    // USART1_TX -> PA9, USART1_RX -> PA10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // USART1 configuration
    USART_InitStructure.USART_BaudRate = 2400;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_Even;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    USART_Cmd(USART1, ENABLE);
}

void GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

    GPIO_InitStructure.GPIO_Pin = LED_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(LED_PORT, &GPIO_InitStructure);
}

void LED_On(void)
{
    GPIO_SetBits(LED_PORT, LED_PIN);
}

void LED_Off(void)
{
    GPIO_ResetBits(LED_PORT, LED_PIN);
}

void MBus_Process(void)
{
    uint8_t ch;

    if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET) {
        return;
    }

    ch = USART_ReceiveData(USART1);

    switch (g_state) {
    case STATE_WAIT_START:
        if (ch == 0x68) {
            g_buf_len = 0;
            g_buf[g_buf_len++] = ch;
            g_state = STATE_WAIT_C;
        }
        break;
    case STATE_WAIT_C:
        if (ch != 0x68) {
            g_state = STATE_WAIT_START;
            break;
        }

        g_buf[g_buf_len++] = ch;
        g_state = STATE_WAIT_L;
        break;
    case STATE_WAIT_L:
        g_buf[g_buf_len++] = ch;
        if (g_buf_len >= 2 && g_buf[1] + 2 == g_buf_len) {
            g_state = STATE_WAIT_DATA;
        }
        break;
    case STATE_WAIT_DATA:
        g_buf[g_buf_len++] = ch;
        if (g_buf_len >= g_buf[1] + 2) {
            g_state = STATE_WAIT_CRC;
        }
        break;
    case STATE_WAIT_CRC:
        g_buf[g_buf_len++] = ch;
        if (g_buf_len >= g_buf[1] + 3) {
            uint8_t crc = 0;
            for (int i = 0; i < g_buf_len - 1; i++) {
                crc += g_buf[i];
            }

            if (crc == g_buf[g_buf_len - 1]) {
                // CRC OK
                switch (g_buf[2]) {
                case 0x51:
                    // readout request
                    g_buf[2] = 0x81;
                    g_buf[3] = 0x01;
                    g_buf[4] = 0x02;
                    g_buf[5] = 0x03;
                    g_buf[6] = 0x04;
                    g_buf[7] = 0x05;
                    g_buf[8] = 0x06;
                    g_buf[9] = 0x07;
                    g_buf[10] = 0x08;
                    g_buf_len = 11;
                    break;
                case 0x52:
                    // reset request
                    g_buf[2] = 0x82;
                    g_buf_len = 3;
                    break;
                case 0x54:
                    // sync request
                    g_buf[2] = 0x84;
                    g_buf_len = 3;
                    break;
                default:
                    break;
                }

                USART_SendData(USART1, 0x68);
                for (int i = 1; i < g_buf_len; i++) {
                    USART_SendData(USART1, g_buf[i]);
                }
                USART_SendData(USART1, crc);
                USART_SendData(USART1, 0x16);
            }
            else {
                // CRC error
            }

            g_state = STATE_WAIT_START;
        }
        break;
    default:
        break;
    }

    if (g_state != STATE_WAIT_START) {
        LED_On();
    }
    else {
        LED_Off();
    }
}
``
用STM32F103写个mbus电表从机的程序

原文地址: https://www.cveoy.top/t/topic/djVS 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录