用STM32F103写个mbus电表从机的程序
由于题目中没有明确的要求,以下是一个简单的示例程序,实现了一个基本的MBus电表从机功能。该程序使用STM32F103作为主控芯片,使用Keil MDK-ARM作为开发环境。
程序包含以下功能:
- 通过USART1与主控通信,收到主控发送的MBus命令后,解析命令并回复对应的应答数据。
- 实现了MBus协议中的数据帧解析和校验功能。
- 通过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();
}
}
``
原文地址: https://www.cveoy.top/t/topic/djVS 著作权归作者所有。请勿转载和采集!