【APM32E030R Micro-EVB开发板评测】——电总协议解析
电总协议又称为空调协议,广泛应用于家用空调和一些高压输电场合,在电力电子当中使用非常的广泛!!!先看数据帧格式!!
1.物理接口
串行通信口采用RS485/RS232。
信息传输方式为异步方式,起始位1位,数据位8位,停止位1位,无校验。
数据传输速率为1200、2400、4800、9600和19200bits可以设置。2.通信方式
在局站内的监控系统为分布式结构。局站监控单元(SU)与设备监控模块(SM)的通信为主从方式,监控单元为上位机,监控模块为下位机。SU呼叫SM并下发命令,SM收到命令后返回响应信息。SU 500ms内接收不到SM响应或接收响应信息错误,则认为本次通信过程失败。
在本系统中,精密空调控制器为SM,上位机为SU。3.1 信息类型
信息分两种类型:
(1) 由SU(上位机)发出到SM(精密空调控制器)的命令信息(简称命令信息);
(2) 由SM(精密空调控制器)返回到SU(上位机)的响应信息(简称响应信息)。在基本格式中的各项除SOI和EOI是以十六进制解释(SOI = 7EH,EOI = 0DH),十六进制传输外,其余各项都是以十六进制解释,以ASCII码的方式传输,每个字节用
两个ASCII码表示,即高四位用一个ASCII码表示,低四位用一个ASCII码表示。例:
CID2 = 4BH,传送时顺序发送34H,42H。
因此,上表以及以下各表中“字节数”是指“解释字节数”,除SOI和EOI外,实际传输字节数应该乘以2。
3.2 基本数据格式
在7.2基本格式中的各项除SOI和EOI是以(SOI = 7EH,EOI = 0DH)十六进制传输外,其余各项都是以ASCII码的方式传输,每个字节用两个ASCII码表示,即高四位一个ASCII码表示,低四位用一个ASCII码表示。例:CID2 = 4BH,传送时顺序发送34H,42H。
LENGTH共2个字节,由LENID和LCHKSUM组成,LENID表示INFO项的ASCII码字节数,
当LENID = 0时,INFO为空,即无该项。LENGTH传输中先传高字节,再传低字节,分四个ASCII码传送。
校验码的计算:D11D10D9D8 + D7D6D5D4 + D3D2D1D0,求和后模16余数取反加1。INFO项的ASCII码字节数为18,即LENID = 0000 0001 0010B。
D11D10D9D8 + D7D6D5D4 + D3D2D1D0 = 0000B + 0001B + 0010B = 0011B,模16余数为0011B,0011B取反加1就是1101B,即LCHKSUM为1101B。
可得:
LENGTH为1101 0000 0001 0010B,即D012H。3.3. CHKSUM 数据格式CHKSUM的计算是除SOI、EOI和CHKSUM外,其他字符按ASCII码值累加求和,所得结果模65536余数取反加1。
收到或发送的字符序列是:“~20014043E00200FD3BCR”(“~”为SOI,“CR”为
EOI),则最后五个字符“FD3BCR”中的FD3B是CHKSUM,计算方法是:
‘2’+‘0’+‘0’+…+‘E’+‘0’+‘0’+‘2’ +‘0’+‘0’
= 32H + 30H + 30H + … + 45H + 30H + 30H + 32H + 30H + 30H= 02C5H
其中‘1’表示1的ASCII码值,‘E’表示E的ASCII码值。02C5H模65536余数是02C5H,02C5H取反加1就是FD3BH。3.4 INFO 数据格式有符号整型数
-32768 ~ +32767
无符号整型数
0 ~ +65535
两个字节的整型数据传送顺序为先高字节后低字节。日期时间格式
CID1、CID2编码分配及分类见表6和表7
1 获取模拟量数据(定点数)(42H)
0x7E,0x21,0x01,0x60,0x42,0x00,0x00,0xFD,0xB0,0x0D
好了,开始进入核心代码
#ifndefCOMM_H#defineCOMM_H
#include "main.h"
#defineREC_MAX 1024 // 定义接收缓存区的大小#defineSEND_MAX1024 // 定义发送缓存区的大小
#defineprint printf
// 通讯常量定义 #defineSERIAL_TIME_ISR 5 // 定时器间隔 ms #defineTIME_OUT 500 // 接收超时时间 500ms #defineTIME_SLEEP 10000 // 休眠超时时间 10S
typedef struct {uint8_tRecBuf; // 接收缓存区uint16_t RecCount; // 接收的字节数uint8_tSendBuf; // 发送缓存区uint16_t SendCount; // 要发送的字节数uint8_tRecOver; // 接收完成标志uint16_t RecTimer; // 接收计时器uint16_t SleepTime; // 休眠计时uint8_tSleepFlag; // 通讯休眠标志} MSG;
typedef enum {Normal,VER_ERROR,CHKSUM_ERROR,LCHKSUM_ERROR,CID2_INVALID,CMD_ERROR,DARA_ERROR,ASCII_ERROR=0x80,} RTN;
extern MSG MSG_SERIAL;extern void SerialInput(uint8_t RevData);extern void SerialTimer(void); // 由定时器调用extern void SerialDecode(void);// 由主函数调用
#endif
#include <string.h>
#include "Serial.h"
#defineSOI 0x7E // 起始标志
#defineVER 0x10 // v1.0
#defineADR 0x01 // 地址描述符
#defineCID1 0x2A // 设备描述符
#defineEOI 0x0D // 结束码
#defineCID2 0x43
MSG MSG_SERIAL;
uint16_t leng_id = 0;
uint16_t leng_id1 = 0;
#defineMODX 0x10000
#definesendData MSG_SERIAL.SendBuf
static uint16_t LENID(void);
static uint8_t LCHKSUM(uint16_t h1);
static uint16_t ChkSum(uint8_t* pData, uint16_t count);
static void SerialTimeOut(void);
static uint8_t atohex16(uint8_t *cp);
static uint8_t RcvChk(void);
static void atoh2b(uint8_t *hp, uint8_t *cp);
static void htoa(uint8_t *pA, uint8_t H);
static void htoa3b(uint8_t *cp, uint16_t h1);
static void htoa4b(uint8_t *cp, uint16_t h1);
static void ClrRcvBuf(void);
static void SerialDecoding(uint8_t pData);
static void SerialStartSend(uint8_t *pData);
staticuint8_t * FloatToChar(float *pFData);
staticfloat * CharToFloat(uint8_t *pChar);
staticuint8_t htoa_H(uint8_t H);
staticuint8_t htoa_L(uint8_t H);
static void SendBuff(void);
static void SerialSend41h(void);
static void SerialSend43h(void);
// 串口接收数据
void SerialInput(uint8_t RecData)
{
if(MSG_SERIAL.RecOver) return; // 停止接收?
if((RecData==SOI)&&(MSG_SERIAL.RecCount==0))
{MSG_SERIAL.SleepTime=0;
MSG_SERIAL.SleepFlag=0;
MSG_SERIAL.RecBuf=SOI;MSG_SERIAL.RecCount=1; // 启动接收
}
else if((MSG_SERIAL.RecBuf==SOI)&&(MSG_SERIAL.RecCount<REC_MAX)) // 如果已经接收到起始位
{
MSG_SERIAL.RecBuf=RecData;
} // 将数据添加到缓存区
else
{
MSG_SERIAL.RecCount=0;
}
if((RecData==EOI)&&(MSG_SERIAL.RecCount==(LENID()+18)))
{
MSG_SERIAL.RecOver=1;
MSG_SERIAL.RecTimer=0; // 清计时器
} //接收完成
}
static uint16_t LENID(void)
{
uint8_tLF_hex = {0};
uint16_t LENGTH = 0;
uint8_tlchsum = 0;
atoh2b(&LF_hex, &MSG_SERIAL.RecBuf);
atoh2b(&LF_hex, &MSG_SERIAL.RecBuf);
LENGTH = (uint16_t)LF_hex<<8|LF_hex;
lchsum = htoa_L((uint8_t) ((~((((LENGTH >> 8)&0x0F) | ((LENGTH >> 4) & 0x0F) | (LENGTH & 0x0F)) % MODX) + 1) & 0x0F));
#if 1
if(lchsum == MSG_SERIAL.RecBuf)
{
leng_id = (uint16_t) (LENGTH & 0x0FFF);
}
#else
leng_id = (uint16_t) (LENGTH & 0x0FFF);
#endif
return leng_id;
}
static uint16_t ChkSum(uint8_t* pData, uint16_t count)
{
uint16_t chkSum = 0;
while (count--)
{
chkSum += (*pData++);
}
chkSum=~chkSum%MODX+1;
return (chkSum);
}
//=============================================================
// CONVERTS 2 ASCII BYTES REPRESENTING A HEX NUMBER INTO BYTE HEX NUMBER.
// ON ENTRY - cp POINTS TO 1ST ASCII BYTE (HIGH NIBBLE OF HEX BYTE),
// - hp POINTS TO A LOCATION TO RECEIVE THE BYTE HEX NUMBER.
//-------------------------------------------------------------
static void atoh2b(uint8_t *hp, uint8_t *cp)
{
// CONVERT 1ST ASCII BYTE TO HIGH NIBBLE OF HEX BYTE:
if (*cp <= '9')
*hp = *cp - '0';
else
{
*cp &= 0xdf; // IF IT'S 'A'-'F' DIGIT MAKE IT UPPERCASE
*hp = *cp - '7';
}
*hp = *hp << 4; // IT'S HIGH NIBBLE OF HEX BYTE
++cp; // POINT TO 2ND ASCII BYTE
// CONVERT 2ND ASCII BYTE TO LOW NIBBLE OF HEX BYTE:
if (*cp <= '9')
*hp += *cp - '0';
else
{
*cp &= 0xdf; // IF IT'S 'A'-'F' DIGIT MAKE IT UPPERCASE
*hp += *cp - '7';
}
return;
}
//=============================================================
// CONVERTS A HEX BYTE NUMBER TO 2 ASCII BYTES REPRESENTING THAT NUMBER.
// ON ENTRY - H HEX BYTE TO BE CONVERTED TO 2 ASCII BYTES,
// - pA POINTS TO 1ST ASCII BYTE WHICH WILL RECEIVE HIGH NIBBLE
// OF HEX NUMBER H.
//-------------------------------------------------------------
static void htoa(uint8_t *pA, uint8_t H)
{
uint8_t h1;
h1 = H >> 4; // h1 = HI NIBBLE OF HEX BYTE
// CONVERT HIGH NIBBLE TO 1ST ASCII BYTE:
if (h1 <= 0x09)
*pA = h1 + '0';
else
*pA = h1 + '7';
++pA; // POINT TO 2ND ASCII BYTE
h1 = H & 0x0f; // h1 = LOW NIBBLE OF HEX BYTE
// CONVERT LOW NIBBLE OF HEX BYTE TO 2ND ASCII BYTE:
if (h1 <= 0x09)
*pA = h1 + '0';
else
*pA = h1 + '7';
++pA; // POINT TO NEXT FREE ASCII BYTE
return;
}
//=============================================================
// CONVERTS A HEX WORD NUMBER TO 4 ASCII BYTES REPRESENTING THAT NUMBER.
// ON ENTRY - h1 HEX BYTE TO BE CONVERTED TO 4 ASCII BYTES,
// - cp POINTS TO 1ST ASCII BYTE WHICH WILL RECEIVE HIGH NIBBLE
// OF HIGH BYTE OF THE HEX NUMBER IN h1.
//-------------------------------------------------------------
static void htoa4b(uint8_t *cp, uint16_t h1)
{
uint8_t c1;
// cp POINTS TO ASCII BYTE 0
// HI NIBBLE OF HI BYTE:
c1 = (uint8_t)(h1 >> 12);
if (c1 <= 0x09)
*cp = c1 + '0';
else
*cp = c1 + '7';
// POINT TO ASCII BYTE 1:
++cp;
// LO NIBBLE OF HI BYTE:
c1 = (uint8_t)((h1 >> 8) & 0x0F);
if (c1 <= 0x09)
*cp = c1 + '0';
else
*cp = c1 + '7';
// POINT TO ASCII BYTE 2:
++cp;
// HI NIBBLE OF LO BYTE:
c1 = (uint8_t)((h1 >> 4) & 0x0F);
if (c1 <= 0x09)
*cp = c1 + '0';
else
*cp = c1 + '7';
// POINT TO ASCII BYTE 3:
++cp;
// LO NIBBLE OF LO BYTE:
c1 = (uint8_t)(h1 & 0x0F);
if (c1 <= 0x09)
*cp = c1 + '0';
else
*cp = c1 + '7';
return;
}
static uint8_t LCHKSUM(uint16_t h1)
{
uint8_t sum = 0;
sum = htoa_L((uint8_t) ((~((((h1 >> 8)&0x0F) | ((h1 >> 4) & 0x0F) | (h1 & 0x0F)) % MODX) + 1) & 0x0F));
//print("sum = 0x%02x\r\n",sum);
return sum;
}
static void htoa3b(uint8_t *cp, uint16_t h1)
{
uint8_t c1;
// LO NIBBLE OF HI BYTE:
c1 = (uint8_t)((h1 >> 8) & 0x0F);//print("c1 = 0x%02x\r\n",c1);
if (c1 <= 0x09)
*cp = c1 + '0';
else
*cp = c1 + '7';
// POINT TO ASCII BYTE 2:
++cp;
// HI NIBBLE OF LO BYTE:
c1 = (uint8_t)((h1 >> 4) & 0x0F);//print("c1 = 0x%02x\r\n",c1);
if (c1 <= 0x09)
*cp = c1 + '0';
else
*cp = c1 + '7';
// POINT TO ASCII BYTE 3:
++cp;
// LO NIBBLE OF LO BYTE:
c1 = (uint8_t)(h1 & 0x0F);//print("c1 = 0x%02x\r\n",c1);
if (c1 <= 0x09)
*cp = c1 + '0';
else
*cp = c1 + '7';
return;
}
static uint8_t atohex16(uint8_t *cp)
{
uint8_t hex = 0;
uint8_t dat1 = 0;
uint8_t dat2 = 0;
// CONVERT 1ST ASCII BYTE TO HIGH NIBBLE OF HEX BYTE:
if (*cp <= '9')
dat1 = *cp - '0';
else
{
*cp &= 0xdf; // IF IT'S 'A'-'F' DIGIT MAKE IT UPPERCASE
dat1 = *cp - '7';
}
++cp; // POINT TO 2ND ASCII BYTE
// CONVERT 2ND ASCII BYTE TO LOW NIBBLE OF HEX BYTE:
if (*cp <= '9')
dat2 += *cp - '0';
else
{
*cp &= 0xdf; // IF IT'S 'A'-'F' DIGIT MAKE IT UPPERCASE
dat2 += *cp - '7';
}
hex = (uint16_t)(dat1<<4|dat2);
return hex;
}
static uint8_t htoa_H(uint8_t H)
{
uint8_t h1 = 0;
uint8_t DATA = 0;
h1 = H >> 4; // h1 = HI NIBBLE OF HEX BYTE
// CONVERT HIGH NIBBLE TO 1ST ASCII BYTE:
if (h1 <= 0x09)
DATA = h1 + '0';
else
DATA = h1 + '7';
return DATA;
}
static uint8_t htoa_L(uint8_t H)
{
uint8_t h1 = 0;
uint8_t DATA = 0;
h1 = H & 0x0f; // h1 = LOW NIBBLE OF HEX BYTE
// CONVERT LOW NIBBLE OF HEX BYTE TO 2ND ASCII BYTE:
if (h1 <= 0x09)
DATA = h1 + '0';
else
DATA = h1 + '7';
return DATA;
}
// 接收数据校验
static uint8_t RcvChk(void)
{
uint8_tLF_TxB = {0};
uint16_t CHKSUM= 0;
atoh2b(&LF_TxB, &MSG_SERIAL.RecBuf);
atoh2b(&LF_TxB, &MSG_SERIAL.RecBuf);
CHKSUM= (uint16_t)(LF_TxB<<8|LF_TxB);
if(CHKSUM==ChkSum(&MSG_SERIAL.RecBuf,12+leng_id))
{return 1;}
else
{return 0;}
}
// 由定时器调用
void SerialTimer(void)
{
if(MSG_SERIAL.RecCount!=0)
{
MSG_SERIAL.RecTimer++;
}
if(MSG_SERIAL.RecCount==0)
{
MSG_SERIAL.SleepTime++;
}
}
// 接收超时处理
static void SerialTimeOut(void)
{
if(MSG_SERIAL.RecTimer>(TIME_OUT/SERIAL_TIME_ISR)) // 如果接收超时
{
MSG_SERIAL.RecCount=0; // 清接收数据计数器
MSG_SERIAL.RecTimer=0; // 清计时器
MSG_SERIAL.RecOver=0; // 允许接
}
if(MSG_SERIAL.SleepFlag) return;
if(MSG_SERIAL.SleepTime>(TIME_SLEEP/SERIAL_TIME_ISR))
{
MSG_SERIAL.SleepFlag=1;
}
}
// 清接收缓存区
static void ClrRcvBuf(void)
{
memset(MSG_SERIAL.RecBuf,0,REC_MAX);
MSG_SERIAL.RecCount=0; // 清接收数据计数器
MSG_SERIAL.RecTimer=0; // 清计时器
MSG_SERIAL.RecOver=0;// 允许接
}
// 数据解码
void SerialDecode(void)
{
SerialTimeOut();
if(!MSG_SERIAL.RecOver) {return;} // 接收没有完成
if(atohex16(&MSG_SERIAL.RecBuf)!= VER) {return;} //
if(atohex16(&MSG_SERIAL.RecBuf)!= ADR) {return;} //
if(atohex16(&MSG_SERIAL.RecBuf)!= CID1) {return;} //
if(!RcvChk()) {return;} // 如果校验错误
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
#if 1
uint16_t i = 0;
print("MSG_SERIAL.RecCount= %d\r\n",MSG_SERIAL.RecCount);
for(i=0;i<MSG_SERIAL.RecCount;i++)
{
print("MSG_SERIAL.RecBuf[%02d]= 0x%02x\r\n",i,MSG_SERIAL.RecBuf);
}
#endif
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
SerialDecoding(atohex16(&MSG_SERIAL.RecBuf)); //
ClrRcvBuf(); // 清缓存区
}
// 将浮点数分解为4个字节
static uint8_t * FloatToChar(float *pFData)
{
void *pVoid;
static uint8_t chart;
uint8_t i;
pVoid=pFData;
for(i=0;i<4;i++)
{
chart=*((uint8_t *)pVoid+i);
}
return (&chart);
}
// 将4个字节 合并为浮点数
static float * CharToFloat(uint8_t *pChar)
{
static float fData;
void *pVoid;
uint8_t i;
pVoid=&fData;
for(i=0;i<4;i++)
{
*((uint8_t *)pVoid+i)=*(pChar+i);
}
return (&fData);
}
// 启动串口发送数据
static void SerialStartSend(uint8_t *pData)
{
uint8_t i;
MSG_SERIAL.SendCount=leng_id1 + 18;
for(i=0;i<MSG_SERIAL.SendCount;i++)
{
MSG_SERIAL.SendBuf=*(pData+i);
}
Serial_SendArray(MSG_SERIAL.SendBuf,MSG_SERIAL.SendCount);
}
// 数据提取
static void SerialDecoding(uint8_t pData)
{
switch(pData)
{
case 0x41:// 电池电压(0x02),电流(0x03),电量(0x04),数据请求
print("0x41\r\n");
SerialSend41h();
break;
case 0x43:// 内部用命令
print("0x43\r\n");
SerialSend43h();
break;
case 0x44:// 内部用命令
print("0x44\r\n");
break;
case 0x4F:// 内部用命令
print("0x4F\r\n");
break;
case 0x50:// 内部用命令
print("0x50\r\n");
break;
case 0x51:// 内部用命令
print("0x51\r\n");
break;
case 0xE1:// 内部用命令
print("0xE1\r\n");
break;
case 0xE2:// 内部用命令
print("0xE2\r\n");
break;
case 0xE3:// 内部用命令
print("0xE3\r\n");
break;
case 0xDB:// 内部用命令
print("0xDB\r\n");
break;
default:
print("unsported command!\r\n");
break;
}
}
static void SendBuff(void)
{
uint8_t index = 0;
sendData = SOI; //print("index = %02d\r\n",index);
sendData = htoa_H(VER);//print("index = %02d\r\n",index);
sendData = htoa_L(VER);
sendData = htoa_H(ADR);
sendData = htoa_L(ADR);
sendData = htoa_H(CID1);
sendData = htoa_L(CID1);
sendData = htoa_H(CID2);
sendData = htoa_L(CID2);//print("index = %02d\r\n",index);
}
static void SerialSend41h(void)
{
uint16_t checksum = 0;
uint8_t i = 0;
SendBuff();
leng_id1 = 18;
sendData=LCHKSUM(leng_id1);//9
htoa3b(&sendData, leng_id1);//10 11 12
sendData=htoa_H(1);sendData=htoa_L(1);//1
sendData=htoa_H(00);sendData=htoa_L(00);sendData=htoa_H(0xFA);sendData=htoa_L(0xFA);
sendData=htoa_H(2);sendData=htoa_L(2);//2
sendData=htoa_H(00);sendData=htoa_L(00);sendData=htoa_H(0xFA);sendData=htoa_L(0xFA);
sendData=htoa_H(3);sendData=htoa_L(3);//3
sendData=htoa_H(00);sendData=htoa_L(00);sendData=htoa_H(0xFA);sendData=htoa_L(0xFA);
checksum = ChkSum(&sendData,12+leng_id1);//print("checksum = 0x%02x\r\n",checksum);
htoa4b(&sendData, checksum);//31 32 33 34
sendData=EOI;
SerialStartSend(sendData); // 启动发送
}
static void SerialSend43h(void)
{
uint16_t checksum = 0;
leng_id1 = 0;
SendBuff();
sendData = LCHKSUM(leng_id1);
htoa3b(&sendData, leng_id1);//10 11 12
checksum = ChkSum(&sendData,12+leng_id1);
htoa4b(&sendData, checksum);
sendData=EOI;
SerialStartSend(sendData); // 启动发送
}
/*!
* @file main.c
*
* @brief Main program body
*
* @version V1.0.2
*
* @date 2025-05-15
*
* @attention
*
*Copyright (C) 2024-2025 Geehy Semiconductor
*
*You may not use this file except in compliance with the
*GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
*The program is only for reference, which is distributed in the hope
*that it will be useful and instructional for customers to develop
*their software. Unless required by applicable law or agreed to in
*writing, the program is distributed on an "AS IS" BASIS, WITHOUT
*ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
*See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
*and limitations under the License.
*/
/* Includes */
#include "main.h"
#include "ebtn_app.h"
#include "Serial.h"
/** @addtogroup Examples
@{
*/
/** @addtogroup USART_Interrupt
@{
*/
/** @defgroup USART_Interrupt_Macros Macros
@{
*/
/* printf function configs to USART1*/
#define DEBUG_USARTUSART1
/**@} end of group USART_Interrupt_Macros */
/** @defgroup USART_Interrupt_Enumerations Enumerations
@{
*/
/**@} end of group USART_Interrupt_Enumerations */
/** @defgroup USART_Interrupt_Structures Structures
@{
*/
/**@} end of group USART_Interrupt_Structures */
/** @defgroup USART_Interrupt_Variables Variables
@{
*/
/**@} end of group USART_Interrupt_Variables */
/** @defgroup USART_Interrupt_Functions Functions
@{
*/
/* System tick */
volatile uint32_t sysTick = 0;
volatile uint32_t g_tfime_5ms = 0;
volatile uint32_t sysTick20ms = 0;
/* USART Write Data */
void USART_Write(USART_T* usart, uint8_t* dat);
uint8_tU1_RxBuff;
uint16_t U1_Rxlen = 0;
uint16_t U1_RxlencntPre = 0;
#define CMD_LEN 64
static char cmd;
static uint8_t cmd_index = 0;
/*!
* @brief Main program
*
* @param None
*
* @retval None
*
* @note
*/
int main(void)
{
GPIO_Config_T gpioConfig;
USART_Config_T usartConfigStruct;
hal_systick_init();
/* Enable GPIO clock */
RCM_EnableAHBPeriphClock(TINY_COM1_TX_GPIO_CLK);
/* Enable COM1 clock */
RCM_EnableAPB2PeriphClock(TINY_COM1_CLK);
/* Enable the BUTTON Clock */
RCM_EnableAHBPeriphClock(KEY1_BUTTON_GPIO_CLK);
RCM_EnableAHBPeriphClock(KEY2_BUTTON_GPIO_CLK);
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
/* Connect PXx to USARTx_Tx */
GPIO_ConfigPinAF(TINY_COM1_TX_GPIO_PORT, TINY_COM1_TX_SOURCE, TINY_COM1_TX_AF);
/* Connect PXx to USARRX_Rx */
GPIO_ConfigPinAF(TINY_COM1_RX_GPIO_PORT, TINY_COM1_RX_SOURCE, TINY_COM1_RX_AF);
/* Configure USART Tx as alternate function push-pull */
gpioConfig.mode = GPIO_MODE_AF;
gpioConfig.pin = TINY_COM1_TX_PIN;
gpioConfig.speed = GPIO_SPEED_50MHz;
gpioConfig.outtype = GPIO_OUT_TYPE_PP;
gpioConfig.pupd = GPIO_PUPD_PU;
GPIO_Config(TINY_COM1_TX_GPIO_PORT, &gpioConfig);
/* Configure USART Rx as input floating */
gpioConfig.pin= TINY_COM1_RX_PIN;
GPIO_Config(TINY_COM1_RX_GPIO_PORT, &gpioConfig);
/* TINY_USARTs configured as follow: */
/* BaudRate = 115200 baud */
usartConfigStruct.baudRate = 115200;
/* Receive and transmit enabled */
usartConfigStruct.mode = USART_MODE_TX_RX;
/* Hardware flow control disabled (RTS and CTS signals) */
usartConfigStruct.hardwareFlowCtrl = USART_FLOW_CTRL_NONE;
/* No parity */
usartConfigStruct.parity = USART_PARITY_NONE;
/* One Stop Bit */
usartConfigStruct.stopBits =USART_STOP_BIT_1;
/* Word Length = 8 Bits */
usartConfigStruct.wordLength = USART_WORD_LEN_8B;
/* USART_Config */
USART_Config(TINY_COM1, &usartConfigStruct);
/* Enable USART_Interrupt_RXBNEIE */
USART_EnableInterrupt(TINY_COM1, USART_INT_RXBNEIE);
NVIC_EnableIRQRequest(TINY_COM1_IRQn, 2);
/* Enable USART */
USART_Enable(TINY_COM1);
RCM_EnableAHBPeriphClock(LED2_GPIO_CLK | LED3_GPIO_CLK);
/* LED2 GPIO configuration */
gpioConfig.pin = LED2_PIN;
gpioConfig.mode = GPIO_MODE_OUT;
gpioConfig.outtype = GPIO_OUT_TYPE_PP;
gpioConfig.speed = GPIO_SPEED_50MHz;
gpioConfig.pupd = GPIO_PUPD_NO;
GPIO_Config(LED2_GPIO_PORT, &gpioConfig);
/* LED3 GPIO configuration */
gpioConfig.pin = LED3_PIN;
GPIO_Config(LED3_GPIO_PORT, &gpioConfig);
/* Turn LED2 on */
//GPIO_ClearBit(LED2_GPIO_PORT, LED2_PIN);
GPIO_SetBit(LED2_GPIO_PORT, LED2_PIN);
/* Turn LED3 off */
GPIO_SetBit(LED3_GPIO_PORT, LED3_PIN);
//GPIO_ClearBit(LED3_GPIO_PORT, LED3_PIN);
/* Configure Button pin as input floating */
gpioConfig.mode = GPIO_MODE_IN;
gpioConfig.pupd = GPIO_PUPD_PU;
gpioConfig.pin = KEY1_BUTTON_PIN;
GPIO_Config(KEY1_BUTTON_GPIO_PORT, &gpioConfig);
gpioConfig.pin = KEY2_BUTTON_PIN;
GPIO_Config(KEY2_BUTTON_GPIO_PORT, &gpioConfig);
ebtn_APP_Key_INIT();
shell_init();
while (1)
{
SerialDecode();
}
}
/*!
* @brief serial port tramsimt data
*
* @param pointer to date that need to be sent
*
* @retval None
*
* @note
*/
void USART_Write(USART_T* usart, uint8_t* dat)
{
while (*dat)
{
while (USART_ReadStatusFlag(usart, USART_FLAG_TXBE) == RESET);
USART_TxData(usart, *dat++);
}
}
void Serial_SendByte(uint8_t Byte)
{
USART_TxData(TINY_COM1, Byte);
while (USART_ReadStatusFlag(TINY_COM1, USART_FLAG_TXBE) == RESET);
}
void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
uint16_t i;
for (i = 0; i < Length; i ++)
{
Serial_SendByte(Array);
}
}
void Serial_SendString(char *String)
{
uint16_t i;
for (i = 0; String != '\0'; i ++)
{
Serial_SendByte(String);
}
}
/*!
* @brief This function handles USART1 RX interrupt Handler
*
* @param None
*
* @retval None
*
* @NOTE This function need to put intovoid USART1_IRQHandler(void)
*/
voidUSART_Receive_Isr(void)
{
uint8_t dat;
if (USART_ReadStatusFlag(TINY_COM1, USART_FLAG_RXBNE) == SET)
{
dat = (uint8_t)USART_RxData(TINY_COM1);
SerialInput(dat);
//if(U1_Rxlen >= sizeof(U1_RxBuff)) U1_Rxlen = 0; //防止串口被刷爆
//U1_RxBuff = dat;
//printf("%c", ReceiveTmp);
}
}
void hal_systick_init(void)
{
SysTick_Config(SystemCoreClock / TICKS_PER_SECONDS);
}
uint32_t HAL_GetTick(void)
{
return sysTick;
}
void HAL_Delay(uint32_t Delay)
{
#define HAL_MAX_DELAY 0xFFFFFFFFU
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
/* Add a freq to guarantee minimum wait */
if (wait < HAL_MAX_DELAY)
{
wait++;
}
while ((HAL_GetTick() - tickstart) < wait)
{
}
}
#if defined (__CC_ARM) || defined (__ICCARM__) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
/*!
* @brief Redirect C Library function printf to serial port.
* After Redirection, you can use printf function.
*
* @param ch:The characters that need to be send.
*
* @param *f:pointer to a FILE that can recording all information
* needed to control a stream
*
* @retval The characters that need to be send.
*
* @note
*/
int fputc(int ch, FILE* f)
{
/* send a byte of data to the serial port */
USART_TxData(DEBUG_USART, (uint8_t)ch);
/* wait for the data to be send*/
while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);
return (ch);
}
#elif defined (__GNUC__)
/*!
* @brief Redirect C Library function printf to serial port.
* After Redirection, you can use printf function.
*
* @param ch:The characters that need to be send.
*
* @retval The characters that need to be send.
*
* @note
*/
int __io_putchar(int ch)
{
/* send a byte of data to the serial port */
USART_TxData(DEBUG_USART, ch);
/* wait for the data to be send*/
while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);
return ch;
}
/*!
* @brief Redirect C Library function printf to serial port.
* After Redirection, you can use printf function.
*
* @param file:Meaningless in this function.
*
* @param *ptr:Buffer pointer for data to be sent.
*
* @param len:Length of data to be sent.
*
* @retval The characters that need to be send.
*
* @note
*/
int _write(int file, char* ptr, int len)
{
int i;
for (i = 0; i < len; i++)
{
__io_putchar(*ptr++);
}
return len;
}
#else
#warning Not supported compiler type
#endif
void user_uart_clear(void)
{
memset(U1_RxBuff, 0, sizeof(U1_RxBuff));
U1_Rxlen = 0;
}
uint8_t user_uart_wait_receive(void)
{
if(U1_Rxlen == 0) //如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数
return REV_WAIT;
if(U1_Rxlen == U1_RxlencntPre) //如果上一次的值和这次相同,则说明接收完毕
{
U1_Rxlen = 0; //清0接收计数
return REV_OK; //返回接收完成标志
}
U1_RxlencntPre = U1_Rxlen; //置为相同
return REV_WAIT; //返回接收未完成标志
}
void shell_init(void)
{
printf("\r\n澶氬姛鑳芥寜閿祴璇曞簱\r\n");
}
void shell_process(void)
{
if(user_uart_wait_receive() == REV_OK)
{
if(strcmp(U1_RxBuff,"LED2_ON") == 0)
{
APM_TINY_LEDOn(LED2);
printf("Led2 点亮!\n");
}
else if(strcmp(U1_RxBuff,"LED2_OFF") == 0)
{
APM_TINY_LEDOff(LED2);
printf("Led2 熄灭!\n");
}
else if(strcmp(U1_RxBuff,"LED3_ON") == 0)
{
APM_TINY_LEDOn(LED3);
printf("Led3 点亮!\n");
}
else if(strcmp(U1_RxBuff,"LED3_OFF") == 0)
{
APM_TINY_LEDOff(LED3);
printf("Led3 熄灭!\n");
}
else if(strcmp(U1_RxBuff,"LED_ON") == 0)
{
APM_TINY_LEDOn(LED2);APM_TINY_LEDOn(LED3);
printf("Led2 Led3 全亮!\n");
}
else if(strcmp(U1_RxBuff,"LED_OFF") == 0)
{
APM_TINY_LEDOff(LED2);APM_TINY_LEDOff(LED3);
printf("Led2 Led3 全灭!\n");
}
user_uart_clear();
}
HAL_Delay(10);
}
/**@} end of group USART_Interrupt_Functions */
/**@} end of group USART_Interrupt */
/**@} end of group Examples */
主函数中直接解析
编译烧录到板子
打开电总协议串口助手
[发送]: 7e 31 30 30 31 32 41 34 33 45 30 30 32 31 31 46 44 32 42 0d (~10012A43E00211FD2B )
[接收]: 7e 31 30 30 31 32 41 34 33 30 30 30 30 46 44 41 34 0d (~10012A430000FDA4 )
[发送]: 7e 31 30 30 31 32 41 34 33 45 30 30 32 32 32 46 44 32 39 0d (~10012A43E00222FD29 )
[接收]: 7e 31 30 30 31 32 41 34 33 30 30 30 30 46 44 41 34 0d (~10012A430000FDA4 )
可以看到数据正常收发
[发送]: 7e 31 30 30 31 32 41 34 33 45 30 30 32 34 31 46 44 32 38 0d (~10012A43E00241FD28 )
[接收]: 7e 31 30 30 31 32 41 34 33 30 30 30 30 46 44 41 34 0d (~10012A430000FDA4 )
这个协议一次性要发送这么的数据帧呀! 霜咬回响 发表于 2025-8-30 15:17
这个协议一次性要发送这么的数据帧呀!
一发一收,没这么多,那是帧内容,不是数据
页:
[1]