本人单片机小白,第一次发帖,这是我做的51单片机串口通信和LCD1602结合的一个程序设计,掉过几个坑,前后共花费了两天的时间。附件里面是程序源代码,自己写的代码,请大家多多指教。之所以写这个帖子,一个算是做一个总结,另一个是写出自己曾经踩到的误区,希望能帮助到其他人。
视频:
本人使用的是STC89C52普中的开发板。 需要实现的效果:在液晶上显示从PC机串口上下发的数据,超屏后清屏并将多余字符从头显示。
总体思路:代码是采用多文件写的,更体现模块化设计,在查找修改错误时更加方便。由于将LCD1602设置为两行显示,一行显示16个字节,两行共32个字节,因此设置一个receivedata[32]的数组,用于存放上位机发送置单片机接收缓存区SBUF的数据,再将数组内容运用LCD1602writedata(uchar)函数,使其能在LCD1602液晶屏上显示。通过数组下标或重新设置一个变量统计液晶屏幕上已显示的字节数,当字节数为16的倍数且不为32的倍数时换行,当字节数为32的倍数时清屏,将多余字符从头显示。
误区一:LCD1602writedata(uchar)函数放入中断函数。
将会遇到的问题:上位机发送字符串,例如123456,LCD1602上只会显示12,缺少3456.这个问题一直困扰了好久,以为是串口通信中断代码函数的错误,导致单片机未能完整接收字符串内容。然而,你可以将划线处注释掉,接着加入: - SBUF =receivedate[num];
- while(!TI);
- TI=0;
复制代码在串口通信助手软件上,你会发现上位机发送的数据,单片机就能完整地发送回来。貌似是存在函数之间的某种冲突,也有可能是代码本身存在着其他错误导致的。总之,LCD1602writedata(uchar)函数最好放在主函数里面。将其移至主函数里面时,不要忘了在中断里面做一个标示,例如flag = 1之类的,使中断完成之后,主函数if(flag)判断语句接收到flag=1为真后,才执行LCD1602writedata(uchar)函数。不然,由于while(1)这个大循环里面,只有一个光秃秃的LCD1602writedata(uchar)函数,你的LCD1602液晶屏上会不断的写入某一字符。
误区二:数组下标num,将num++放入主函数中,企图通过LCD1602初始化设置的指令——每增加一字符,光标自动右移来实现数组数据的显示,且未注意num值在中断结束时的值(因对串口中断不完全理解导致)。
将会遇到的问题:上位机发送字符,LCD1602上总是只会在同一处地方显示一位字节。需要将num++移回中断,数组接收下标增加要在中断中完成,只要一有中断信号就会触发,中断函数它不会在主函数里面等num++,之后再去响应中断信号,中断就是一个连续的过程,可以说是中间没有停顿的一次性将接受缓冲区SBUF里面的数据都存放到数组中,然而,将num++放入中断函数中,若不加注意,这又牵扯到我原本程序中的另一个错误,未注意num中断结束时的值,即主函数中LCDwritedata(receivedate[num])执行时,num并不等于0的。即数据并不是从头开始输出到LCD液晶屏上。这里就需要使用一个for循环函数。
误区三:未注意数组下标的值和for循环次数n的值,或者说逻辑不清晰,例如原本的错误代码:
将会遇到的问题:例如输入1234,上位机第一次发送,LCD1602显示正常,第二次发送,LCD1602显示1234会重复两边,第三次发送,LCD1602显示1234会重复三遍,以此类推。。。。。。原因是num = 0放错位置,中断中的num++会使num值不断增加,然而n==32的判定值也会是num=0几乎如同天方夜谭,我在这里就犯了逻辑混乱的错误,静下来重新再理一遍就会发现问题,重新定义一个变量total,专门用来计数已经在LCD液晶屏上显示过的字节总数,不再依靠数组下标来判断什么时候换行,什么时候清屏。 误区三错误效果演示: [已上传至附件]
单片机的学习结果是充满欢乐的,但过程是痛苦的,尤其是遇到问题,百度搜索也找不到自己想要的答案。希望这篇贴文能填补一些空缺,帮助到需要帮助的人。
全部资料51hei下载地址:
误区三错误效果演示.rar
(4.89 MB, 下载次数: 114)
串口通信LCD1602.rar
(41.27 KB, 下载次数: 397)
|