串口主从通信方式 单片机从机实现

这里的demo是1对1的通讯的,1对多修改协议增加从机地址字段,并修改相关使用即可,这里截取项目中一个通讯任务。
硬件平台  STM32   系统 freertos

// #inlcude  略



typedef struct{
	uint8_t len;
	uint8_t msg;
	uint8_t payloadLen;
}_msg;

#define FRAME_END_TIME	50//ms  
#define RX_BUFFER_SIZE	256
#define TX_BUFFER_SIZE	256
static uint8_t RxBuffer[RX_BUFFER_SIZE];
static uint8_t TxBuffer[TX_BUFFER_SIZE];
static uint16_t Rx_p=0;
static uint8_t FrameStatus=1;
static int nowRxTick=-1;
static int lastRxTicke=0;

extern uint32_t Sys_ms_Tick;//递增
extern uint8_t Source[];
extern uint8_t Destination[];
extern char IMEI[];
extern char IOT_IP[];
extern char NB_IOT_NET[];

static void InterruptReviceCallback(uint8_t a)
{
	
		if(0==FrameStatus)
		{
			if(Rx_p<RX_BUFFER_SIZE)
			{
				RxBuffer[Rx_p++] = a;
			}
			nowRxTick = Sys_ms_Tick;			
		}	
		
}

static void ReviceBegin()
{
	if(FrameStatus==1)
	{
		FrameStatus = 0;
		Rx_p = 0;
		nowRxTick = -1;
		lastRxTicke = 0;
	}
}


static int GetFrame()
{	
	if(nowRxTick!=-1)
	{
		if(nowRxTick==lastRxTicke)
		{
			FrameStatus = 1;
			return 1;
		}
		else
		{
			lastRxTicke = nowRxTick;
			return 0;
		}
	}
	return 0;
}

static void SendFrame()
{
	uint16_t crc16;
	uint8_t len = TxBuffer[0]; 
	crc16 = Crc16_Modbus(TxBuffer,len-2);
	TxBuffer[len-2] = crc16;
	TxBuffer[len-1] = crc16>>8;
	HAL_UART_Transmit(&huart1,TxBuffer,len,0xffff);
}


void DebugInit()
{
	UART1_Callback = InterruptReviceCallback;//回调估值
	StartUART_Rx(&huart1);//启动串口驱动
	FrameStatus=1;
	Urt1ReviceBegin();//开始接收
}


void DebugTask()
{
	_msg *rmsg=(_msg*)RxBuffer;
	_msg *tmsg=(_msg*)TxBuffer;
	
	uint8_t *rpayload = &RxBuffer[3];
	uint8_t *tpayload = &TxBuffer[3];
	uint8_t len=0;
	uint16_t temp;
	DebugInit();
	while(1)
	{
		osDelay(FRAME_END_TIME);
		if(GetUsart1Frame())
		{
			if(0==Crc16_Modbus(RxBuffer,Rx_p))
			{
				switch(rmsg->msg)
				{
					case 0x01:
						tmsg->len=5+6;
						tmsg->msg=0x81;
						tmsg->payloadLen=6;
						memcpy(tpayload,Source,6);
						SendFrame();
					break;
					case 0x02:
						if(rmsg->len==11)
						{
							memcpy(Source,rpayload,6);			
						}
						tmsg->len=5+0;
						tmsg->msg=0x82;
						tmsg->payloadLen=0;	
						
						SendFrame();					
					break;
					case 0x03:
						tmsg->len=5+6;
						tmsg->msg=0x83;
						tmsg->payloadLen=6;
						memcpy(tpayload,Destination,6);
						SendFrame();
					break;	
					case 0x04:
						memcpy(Destination,rpayload,6);			
						tmsg->len=5+0;
						tmsg->msg=0x84;
						tmsg->payloadLen=0;	
						SendFrame();					
					break;
					case 0x05:
						tmsg->len=5+strlen(IMEI)+1;
						tmsg->msg=0x85;
						tmsg->payloadLen=strlen(IMEI)+1;
						memcpy(tpayload,IMEI,strlen(IMEI)+1);
						SendFrame();
					break;	
					case 0x06:
						tmsg->len=5+strlen(IOT_IP)+1;
						tmsg->msg=0x86;
						tmsg->payloadLen=strlen(IOT_IP)+1;
						memcpy(tpayload,IOT_IP,strlen(IOT_IP)+1);
						SendFrame();
					break;
					case 0x07:
						len = strlen((char*)rpayload);
						if(len<64)
						{							
							memcpy(IOT_IP,rpayload,strlen((char*)rpayload));		
							tmsg->len=5+1;
							tmsg->msg=0x87;
							tmsg->payloadLen=1;
							tpayload[0] = 0;
							SendFrame();					
						}
						else
						{
							tmsg->len=5+1;
							tmsg->msg=0x87;
							tmsg->payloadLen=1;
							tpayload[0] = 1;
							SendFrame();	
						}
					break;
					case 0x08:
						tmsg->len=5+strlen(NB_IOT_NET)+1;
						tmsg->msg=0x88;
						tmsg->payloadLen=strlen(NB_IOT_NET)+1;
						memcpy(tpayload,NB_IOT_NET,strlen(NB_IOT_NET)+1);
						SendFrame();
					break;
					case 0x09:
						len = strlen((char*)rpayload);
						if(len<64)
						{
							memcpy(NB_IOT_NET,rpayload,strlen((char*)rpayload));		
							tmsg->len=5+1;
							tmsg->msg=0x89;
							tmsg->payloadLen=1;
							tpayload[0] = 0;
							SendFrame();					
						}
						else
						{
							tmsg->len=5+1;
							tmsg->msg=0x89;
							tmsg->payloadLen=1;
							tpayload[0] = 1;
							SendFrame();	
						}
					break;				
					case 0x0a:
						SaveSysInfo();
						tmsg->len=5;
						tmsg->msg=0x8a;
						tmsg->payloadLen=0;
						SendFrame();		
					break;
					case 0x0b:
						memset(Source,0,6);
						Source[5]=1;
						memset(Destination,0,6);
						Destination[5]=1;
						strcpy(IMEI,"000000000");
						strcpy(IOT_IP,"AT+NCDP=180.101.147.115,5683\r\n");
						strcpy(NB_IOT_NET,"AT+CGDCONT=1,\"IP\",\"ctnet\"\r\n");
						SaveSysInfo();
						SYS.uploadTime = 60;
						SaveInitInfo();
						tmsg->len=5;
						tmsg->msg=0x8b;
						tmsg->payloadLen=1;
						SendFrame();
					break;
					case 0x0c:
						tmsg->len=5+strlen(COMPY_ID)+1;
						tmsg->msg=0x8c;
						tmsg->payloadLen=strlen(COMPY_ID)+1;
						memcpy(tpayload,COMPY_ID,strlen(COMPY_ID)+1);
						SendFrame();
					break;
									
					case 0x0d:				
						SYS.terminalMode=0;
						SaveInitInfo();
					  osDelay(50);
					  printf("搜索准备成功正在重启\r\n");
						HAL_NVIC_SystemReset();
					break;				
					case 0x0e:												
						SYS.terminalMode=2;
						SaveInitInfo();
						SaveTerminalInfo();
					  osDelay(50);				
						printf("保存成功正在重启\r\n");
						HAL_NVIC_SystemReset();
					break;				
					case 0x0f:
						printf("det%d个,arc%d个,ocp%d个,mmn%d个\r\n",SYS.detectorNum,SYS.arcDetectorNum,SYS.ocpNum,SYS.multiMeterNum);
					break;
					case 0x10:
						temp = rpayload[0]|rpayload[1]<<8;
						if(temp>0&&temp<2000)
						{
							SYS.uploadTime = temp;
							SaveInitInfo();
							tmsg->len=5+1;
							tmsg->msg=0x90;
							tmsg->payloadLen=1;
							tpayload[0] = 0;
							SendFrame();
						}
						else
						{
							tmsg->len=5+1;
							tmsg->msg=0x90;
							tmsg->payloadLen=1;
							tpayload[0] = 1;
							SendFrame();	
						}
						
					break;
					case 0x11:
						tmsg->len=5+2;
						tmsg->msg=0x91;
						tmsg->payloadLen=2;
						tpayload[0] = SYS.uploadTime;
						tpayload[1] = SYS.uploadTime>>8;						
						SendFrame();
					break;
					
					case 0x7f:
						tmsg->len=5;
						tmsg->msg=0xff;
						tmsg->payloadLen=0;
						SendFrame();
						osDelay(50);
						HAL_NVIC_SystemReset();
					break;
					
					default:break;
				}							
			}	
			ReviceBegin();			
		}
	}
}

根据主机设置好超时参数 FRAME_END_TIME,连续的两个字节时间超过FRAME_END_TIME即判断为一帧完成,这里借鉴了modbus-rtu断帧方式。
freertos开机新建一个任务,然后把DebugInit()放到while(1)中即可,底层硬件初始化略,UART1_Callback()串口中断回掉函数,Sys_ms_Tick 1ms 自增1
  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值