天天看点

51单片机485通信(时控开关)新塘51单片机485通信总结前言一、步骤二、遇到的问题总结

新塘51单片机485通信总结

前因:最近要用51单片机来跑一个控制继电器的控制板。

主要应用:485通信,51单片机。

提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 新塘51单片机485通信总结
  • 前言
  • 一、步骤
  • 二、遇到的问题
  • 总结

前言

项目目标:上位机通过485和新塘51单片机通信,控制1-4个时控开关控制板的继电器.

难点:

(1)单片机485通信(没作用485通信)

(2)和上位机通信的协议(这个协议太费劲)

(3)和上位机通信时上位机新建线程。

一、步骤

(1)完成PC通过485来和时控开关部分通信

(2) 完成上位机测试代码

(3)增加时控开关的错误处理,并修改协议和上位机一起测试。

二、遇到的问题

1Q:上位机接收到乱码。

A:链路链接不限问题(A,B线接反了)。

2Q:单片机在115200下无法通信。但是19200和9600OK。

A:可能是使用的初始化代码出现问题了。具体是什么问题我没有去深究。

注意:这个使用115200发送数据的时候要加延时!J = 100 ;J-- 。

代码如下(示例):

/*正确的初始化*/
void UART_Init(uint32_t Bound)
{
	MODIFY_HIRC(HIRC_24);
    P06_QUASI_MODE;
	P07_QUASI_MODE;
	
    UART_Open(24000000,UART0_Timer3,Bound);
	
    ENABLE_UART0_PRINTF; 
	ENABLE_UART0_INTERRUPT;//开
	
	TI = 0;
	RI = 0;
	EA = 1;
}
/*错误的初始化*/
void InitialUART0_Timer1(UINT32 u32Baudrate)    //T1M = 1, SMOD = 1
{
	P06_Quasi_Mode;		//Setting UART pin as Quasi mode for transmit
	P07_Quasi_Mode;		//Setting UART pin as Quasi mode for transmit
	
    SCON = 0x50;     	//UART0 Mode1,REN=1,TI=1
    TMOD |= 0x20;    	//Timer1 Mode1
    
    set_SMOD;        	//UART0 Double Rate Enable
    set_T1M;
    clr_BRCK;        	//Serial port 0 baud rate clock source = Timer1
 
#ifdef FOSC_160000
    TH1 = 256 - (1000000/u32Baudrate+1);               /*16 MHz */
#endif    	
#ifdef FOSC_166000
    TH1 = 256 - (1037500/u32Baudrate);         		     /*16.6 MHz */
#endif
    set_TR1;
		clr_TI;						//For printf function must setting TI = 1
		clr_RI;
		
    set_ES;           //enable UART interrupt
    set_EA;           //enable global interrupt
}
           

3Q:时控开关通信时出现错误数据

A:在上位机和时控开关通信时出现时控开关回复的数据出现错误,但是时控开关可以相应动作并且正确回复CRC(ModBus),这遇见这个问题是时检查了一下代码并发现错误和相关警告。后来我将这个全局的数组改成了局部的数据。在每次调用时重新赋值。调用结束就回收内存。解决了在不确定的时间出现时控开关发送错误数据的问题。

注意:这个问题可能是因为单片机内存太小了,我使用的片内RAM只有256字节。这个可能是由于内存溢出了。我将这个全局数组放到局部上,Keil提示内存不对。后来百度了一下说是内存超过了片内RAM,我就改成了片外存储。就是片外存储得用DPTR指令,而且我这个数组是经常调用的。速度会慢一些。后续可能会改一下存储区域重新分配下内存。后来就没有这个发送数据数据错误的问题了。

https://www.cnblogs.com/jikexianfeng/p/5870357.html

(转载)这个讲内存挺不错的。

51单片机485通信(时控开关)新塘51单片机485通信总结前言一、步骤二、遇到的问题总结
/**/
static uint8_t TimSwitch_Agreement_Explain(void)
{
	uint16_t CRC_Value;
	uint8_t i;
	uint8_t CRC_Array[8] = { 0X00};
	uint8_t Send_Array[11]=
	{
	0X00, 0X40, 0X00, 0X03, 0X00, 0X01, 0X01 , 0x00, 0X00, 0X00
	};	
           

4Q:每次发送数据延时的问题,波特率都是115200。

A:在和PC的上位机通信时单片机延时100自减就可以,但是在和X1000的芯片通信时就得10000个本征函数。这个在和PC通信时延时的时候延时10000个本征函数就会很“稳”,稳不稳我也不知道就是在PC串口助手上看接收到的数据会看起来接收的慢一点。我也不知道哪个好,就是要加延时才能正常通信。原因我也不懂!

5Q:多机通信和错误处理

A:这个控制板是多机通信,多个控制板都挂在一个485总线上。如果说多机通信有问题,那么一定是因为上位机发送给时空开关的是8个字节,但是时控开关的回复是9个字节。那么在多机通信时时控开关的回复信息将数据挂载到总线上,总线上所有的从机都会接收到9个字节。正常所有从机接收到8个字节后就去解析数据了,当有第九个数据时就会产生冲突(函数解析到一半进入中断了),为了避免这个情况1.函数解析关闭中断2.接收到第九个字节后立刻跳转到错误处理函数。

总结

万事开头难,第一个单片就的项目基本就结束了。真是不容易啊,这个项目的目标一点点变化。从一开始做引脚终端,再到做485通信,在做微光协议。再加地址判断,再换MODBUS协议,再写上位机,再加错误处理,联调。

遇到了很多小问题(1)单片机烧录问题(2)数组引用越界(3)定义数据错误:定义uint8_t,赋值时10000(用于延时计数),这尼玛就离谱,后果就是发送不出数据。(4)memset清除数组。(5)485没接触好。(6)485总线接到示波器探头会一直拉高总线等。

问题都会被解决的,没解决是没找对方法,没想对原因(这就是废话,但是真有道理)。这个项目做了两个月,本以为是做21天,但是超时这么多。代码从50行到400行。多少个我觉得我不能解决的问题,多少个我觉得很难的事,都过去了,想清楚原因,去尝试。我们失败的原因有无数个,但是我们成功的原因只有一个,那就是我们提前想到可能会出现的问题并避免了这个问题。前面有个坑,不掉进去永远不知道那里有个坑。想想可能会出现问题的地方。问题都会解决的,耐心点。有时候一个问题卡住太久了,就别机械性的去漫无目的尝试,休息下,换个思路再去试试。所有的问题会卡住都是因为不了解原理,或是对整个过程理解不充分,想一下整个过程是什么样的,实际又是什么样的。不要总是我以为,尊重事实 加油!明天会更好!