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

这里的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>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

你可能感兴趣的:(串口主从通信方式 单片机从机实现)