如何为编程爱好者设计一款好玩的智能硬件(九)——LCD1602点阵字符型液晶显示模块驱动封装(下)
六、温湿度传感器DHT11驱动封装(下):如何为编程爱好者设计一款好玩的智能硬件(六)——初尝试·把温湿度给收集了(下)!
七、点阵字符型液晶显示模块LCD1602驱动封装(上):如何为编程爱好者设计一款好玩的智能硬件(七)——LCD1602点阵字符型液晶显示模块驱动封装(上)
八、LCD1602点阵字符型液晶显示模块驱动封装(中):如何为编程爱好者设计一款好玩的智能硬件(八)——LCD1602点阵字符型液晶显示模块驱动封装(中)
九、LCD1602点阵字符型液晶显示模块驱动封装(下)
在上文中我们终于实现了一个简单版的无线滚动屏!本节对其工程进行详细讲解——
工程概述
keil u5 PK51IDE
无线显示屏采用蓝牙串口透传模块和LCD1602液晶显示模块
单片机采用STC89C51单片机
实现上位机通过串口助手发送一行msg,其在LCD屏上显示出来
要求msg长度小于32
更多详情请见前两节内容
1、LCD1602封装——LCD1602.C内部封装(一般不要改动)用的时候只需要根据平台重新修改.h内的宏定义即可
下面3个函数是基础通信函数,分别负责忙检测、写命令和写数据。具体细节可以参考——如何为编程爱好者设计一款好玩的智能硬件(七)——LCD1602点阵字符型液晶显示模块驱动封装(上))
- //------------------------------------------------
- //base communite function
- t_uc LCD1602_CheckBusy(void)//check busy
- {
- t_c temp_data;
- LCD1602_DATA_PORT_WRITE(0xFF);
- LCD1602_RS_PIN_CLEAR;
- LCD1602_RW_PIN_SET;
- LCD1602_EN_PIN_CLEAR;
- LCD1602_NOP;
- LCD1602_EN_PIN_SET;
- LCD1602_DATA_PORT_READ(&temp_data);
- return (temp_data & 0x80);
- }
- void LCD1602_WriteCom(t_uc com)//write command
- {
- while(LCD1602_CheckBusy()); //if busy wait
- LCD1602_RS_PIN_CLEAR;
- LCD1602_RW_PIN_CLEAR;
- LCD1602_EN_PIN_SET;
- LCD1602_DATA_PORT_WRITE(com);
- LCD1602_NOP;
- LCD1602_EN_PIN_CLEAR;
- }
- void LCD1602_WriteData(t_uc temp_data)//write data
- {
- while(LCD1602_CheckBusy()); //if busy wait
- LCD1602_RS_PIN_SET;
- LCD1602_RW_PIN_CLEAR;
- LCD1602_EN_PIN_SET;
- LCD1602_DATA_PORT_WRITE(temp_data);
- LCD1602_NOP;
- LCD1602_EN_PIN_CLEAR;
- }
下面的LCD1602初始化函数负责对LCD显示模式进行设置,如设置是否有光标、设置memory指针的方向...关于初始化为什么这样以及这些命令表示什么意思,可以参考——如何为编程爱好者设计一款好玩的智能硬件(七)——LCD1602点阵字符型液晶显示模块驱动封装(上))
- //------------------------------------------------
- //initialization function
- void LCD1602_Init(void)
- {
- LCD1602_WriteCom(0x38); /*display mode settings*/
- LCD1602_DELAY_MS();
- LCD1602_WriteCom(0x38);
- LCD1602_DELAY_MS();
- LCD1602_WriteCom(0x38);
- LCD1602_DELAY_MS();
- LCD1602_WriteCom(0x38);
- LCD1602_WriteCom(0x08); /*display close*/
- LCD1602_WriteCom(0x01); /*display clear*/
- LCD1602_WriteCom(0x06); /*display cursor movement settings*/
- LCD1602_DELAY_MS();
- LCD1602_WriteCom(0x0C); /*display and cursor settings*/
- }
下面是一些基于LCD1602基本通信函数封装的功能函数:
void LCD1602_Clear(void)//clear screen 是清屏函数
void LCD1602_WriteChar(t_uc x,t_uc y,t_uc temp_data)//(x,y),data,ascill 是控制在16X2的LCD显示屏上某个位置(x,y)显示一个字符temp_data的函数
void LCD1602_WriteString(t_uc x,t_uc y,t_uc *s)//(x,y),string data 是在第一行(y==0)或在第二行(y==1)的第x个位置显示一个字符串s,不支持自动换行
void LCD1602_ShowMessage(t_uc from,t_uc *s,t_uc delay_ms)//from(0~31),msg,each char delay time 是从0~31显示屏的某个位置开始显示完字符串s,并且显示每个字符间隔时间delay_ms,这里字符串不能超出屏的范围!
写入某个位置某个内容参见——如何为编程爱好者设计一款好玩的智能硬件(七)——LCD1602点阵字符型液晶显示模块驱动封装(上))的内存映射和指令说明小节
- //------------------------------------------------
- //Function
- void LCD1602_Clear(void)//clear screen
- {
- LCD1602_WriteCom(0x01);
- LCD1602_DELAY_MS();
- }
- void LCD1602_WriteChar(t_uc x,t_uc y,t_uc temp_data)//(x,y),data,ascill
- {
- if (y == )//the first line
- {
- LCD1602_WriteCom(0x80 + x);
- }
- else//the second line
- {
- LCD1602_WriteCom(0xC0 + x);
- }
- LCD1602_WriteData(temp_data);
- }
- void LCD1602_WriteString(t_uc x,t_uc y,t_uc *s)//(x,y),string data
- {
- if (y == )//the first line
- {
- LCD1602_WriteCom(0x80 + x);
- }
- else//the second line
- {
- LCD1602_WriteCom(0xC0 + x);
- }
- while (*s)
- {
- LCD1602_WriteData( *s);
- s ++;
- }
- }
- void LCD1602_ShowMessage(t_uc from,t_uc *s,t_uc delay_ms)//from(0~31),msg,each char delay time
- {
- t_uc i;
- t_uc to=from+strlen((t_c*)s)-;
- if(from< || from> || to< || to>)return;//shouldn't out the 32 datas
- if(to<){//only the first line
- LCD1602_WriteCom(0x80 + from);
- for(i=from;i<=to;i++){
- LCD1602_WriteData(s[i]);
- LCD1602_DELAY_MS(delay_ms);
- }
- }else if(from>){//only the sencond line
- LCD1602_WriteCom(0xC0 + from);
- for(i=from;i<=to;i++){
- LCD1602_WriteData(s[i]);
- LCD1602_DELAY_MS(delay_ms);
- }
- }else{//both lines
- LCD1602_WriteCom(0x80 + from);
- for(i=from;i<;i++){
- LCD1602_WriteData(s[i]);
- LCD1602_DELAY_MS(delay_ms);
- }
- LCD1602_WriteCom(0xC0 + from);
- for(i=;i<=to;i++){
- LCD1602_WriteData(s[i]);
- LCD1602_DELAY_MS(delay_ms);
- }
- }
- }
2、LCD1602封装——LCD1602.h根据平台重新修改.h内的宏定义适应不同硬件平台
下面是根据AT89C52的平台特性对宏进行的修改,由于51单片机引脚操作比较简单,且支持读写,无需切换属性~因此下面部分宏定义的功能可以不定义~但是对于STM32就比较复杂了!正因如此,我STM32的封装也没想到一个比较好的处理方式,在我的工程里有基于STM32宏定义修改,不过存在问题,如果今后要用,一定要修改好!!!
- #define MCU_AT89C52
- //////////////////////////////////////////////////////////////////////////////////////////
- //MCU_AT89C52
- //////////////////////////////////////////////////////////////////////////////////////////
- #ifdef MCU_AT89C52
- #include "FUNC/delay.h"
- #include <intrins.h>
- #include <string.h>
- //some typedef need to do
- typedef unsigned char t_uc;
- typedef unsigned short t_us;
- typedef unsigned int t_ui;
- typedef char t_c;
- typedef short t_s;
- typedef int t_i;
- sbit sLCD1602_RS_PIN = P1^;
- sbit sLCD1602_RW_PIN = P1^;
- sbit sLCD1602_EN_PIN = P2^;
- #define LCD1602_DELAY_MS(x) DelayMs((x))
- #define LCD1602_NOP _nop_()
- #define LCD1602_RS_PIN sLCD1602_RS_PIN
- #define LCD1602_RS_PIN_SET LCD1602_RS_PIN=1
- #define LCD1602_RS_PIN_CLEAR LCD1602_RS_PIN=0
- #define LCD1602_RS_PIN_OUT
- #define LCD1602_RW_PIN sLCD1602_RW_PIN
- #define LCD1602_RW_PIN_SET LCD1602_RW_PIN=1
- #define LCD1602_RW_PIN_CLEAR LCD1602_RW_PIN=0
- #define LCD1602_RW_PIN_OUT
- #define LCD1602_EN_PIN sLCD1602_EN_PIN
- #define LCD1602_EN_PIN_SET LCD1602_EN_PIN=1
- #define LCD1602_EN_PIN_CLEAR LCD1602_EN_PIN=0
- #define LCD1602_EN_PIN_OUT
- #define LCD1602_DATA_PORT_GPIO P0
- #define LCD1602_DATA_PORT_IN
- #define LCD1602_DATA_PORT_OUT
- #define LCD1602_DATA_PORT_READ(x) (*(x))=LCD1602_DATA_PORT_GPIO
- #define LCD1602_DATA_PORT_WRITE(x) LCD1602_DATA_PORT_GPIO=(x)
- void LCD1602_WriteCom(t_uc com);//write command
- void LCD1602_WriteData(t_uc temp_data);//write data
- void LCD1602_Init(void);//initialization function
- void LCD1602_Clear(void);//clear screen
- void LCD1602_WriteChar(t_uc x,t_uc y,t_uc temp_data);//(x,y),data,ascill
- void LCD1602_WriteString(t_uc x,t_uc y,t_uc *s);//(x,y),string data
- void LCD1602_ShowMessage(t_uc from,t_uc *s,t_uc delay_ms);//from(0~31),msg,each char delay time
- #endif
3、工程整体逻辑简单梳理
main函数中不断检测串口是否发来有效数据(暂且把一行当为有效数据),一旦有效数据到来就调用ShowMessage显示出来~
- /*------------------------------------------------
- 主函数
- ------------------------------------------------*/
- void main (void)
- {
- InitUART();
- LCD1602_Init();
- LCD1602_Clear();//ÇåÆÁ
- while ()
- {
- //LCD1602_ShowMessage(0,"hello world! I'm beautifulzzzz.",1000);
- if(flag==)
- {
- flag=;
- SendStr(getByte);
- LCD1602_Clear();
- LCD1602_ShowMessage(,getByte,);
- }
- // LCD1602_WriteChar(7, 0, 'o');
- // LCD1602_WriteChar(8, 0, 'k');
- // LCD1602_WriteString(3, 1, "Hard Work");
- //while(1);
- }
- }
串口中断是每收到一行置flag标志位为1,一旦point超过getByte大小就从0开始填充~
- /*------------------------------------------------
- 串口中断程序
- ------------------------------------------------*/
- void UART_SER (void) interrupt //串行中断服务程序
- {
- if(RI){ //判断是接收中断产生
- RI=; //标志位清零
- getByte[point]=SBUF; //读入缓冲区的值
- if((point>) && (getByte[point-]==0x0d) && (getByte[point]==0x0a)){
- getByte[point-]=0x00;
- flag=;
- point=;
- }else{
- point++;
- if(point==){
- point=;
- }
- }
- }
- }
小结&接下来计划:
终于,我们把LCD1602的驱动封装好了!并且修改了之前模块化模块的想法,引入新的设计方式——模块化功能组件的方式(功能组件一般有单片机、通信模块加传感器、显示器、按键或者机械装置组成)。
模块化模块:之前目标是对每个模块封装,使模块灵活适应各种组合(MCU+POWER+X1+X2+...)
模块化功能块:现在是分出基础部分(MCU+POWER+radio)+一个变动部分=构成功能块
因此,接下来我们将会涉足"X-OS"比较重要的一块——基础部分中的无线通信基础部分。而我们首先尝试的将是最赤裸的24L01无线2.4G通信模块驱动的封装!请持续关注~
链接:http://pan.baidu.com/s/1pJMPuJL
[三个关键文件夹说明]
第一个是:LCD1602封装上参考的几个例程
第二个是:(上)参考的datasheet
第三个是:(下)中的工程
@beautifulzzzz
2015-10-02 持续更新中~
如何为编程爱好者设计一款好玩的智能硬件(九)——LCD1602点阵字符型液晶显示模块驱动封装(下)的更多相关文章
- 如何为编程爱好者设计一款好玩的智能硬件(八)——LCD1602点阵字符型液晶显示模块驱动封装(中)
六.温湿度传感器DHT11驱动封装(下):如何为编程爱好者设计一款好玩的智能硬件(六)——初尝试·把温湿度给收集了(下)! 七.点阵字符型液晶显示模块LCD1602驱动封装(上):如何为编程爱好者设计 ...
- 如何为编程爱好者设计一款好玩的智能硬件(七)——LCD1602点阵字符型液晶显示模块驱动封装(上)
当前进展: 一.我的构想:如何为编程爱好者设计一款好玩的智能硬件(一)——即插即用.积木化.功能重组的智能硬件模块构想 二.别人家的孩子:如何为编程爱好者设计一款好玩的智能硬件(二)——别人是如何设计 ...
- 如何为编程爱好者设计一款好玩的智能硬件(十)——无线2.4G通信模块研究·一篇说完
六.温湿度传感器DHT11驱动封装(下):如何为编程爱好者设计一款好玩的智能硬件(六)——初尝试·把温湿度给收集了(下)! 七.点阵字符型液晶显示模块LCD1602驱动封装(上):如何为编程爱好者设计 ...
- 如何为编程爱好者设计一款好玩的智能硬件(三)——该选什么样的MCU呢?
一.我的构想:如何为编程爱好者设计一款好玩的智能硬件(一)——即插即用.积木化.功能重组的智能硬件模块构想 二.别人家的孩子:如何为编程爱好者设计一款好玩的智能硬件(二)——别人是如何设计硬件积木的! ...
- 程序员编程利器:20款最好的免费的IDEs和编辑器
程序员编程利器:20款最好的免费的IDEs和编辑器 还没转眼明年可就大年三十了,忙的可真是晕头转了个向,看着亲朋好友们那让人欣羡的小肚腩,不禁感慨,岁月是一把猪饲料,绿了芭蕉,肥了那杨柳小蛮腰,可怜我 ...
- IOS开发入门教程-总结篇-写给狂热的编程爱好者们
程序发轻狂,代码阑珊,苹果开发安卓狂!--写给狂热的编程爱好者们 写在前面的话 学习iOS应用程序开发已有一段时间,最近稍微闲下来了,正好也想记录一下前阶段的整个学习过程.索性就从最基础的开始,一步一 ...
- Java Socket 网络编程心跳设计概念
Java Socket 网络编程心跳设计概念 1.一般是用来判断对方(设备,进程或其它网元)是否正常动行,一 般采用定时发送简单的通讯包,如果在指定时间段内未收到对方响应,则判断对方已经当掉.用于 ...
- 五款好玩又好用的Linux网络测试和监控工具
五款好玩又好用的Linux网络测试和监控工具 [51CTO精选译文]在这篇介绍几款Linux网络测试实用工具的文章中,我们使用Bandwidthd.Speedometer.Nethogs.Darkst ...
- 如何设计一款优秀的短视频 SDK
2017 年,短视频成为了创业的新风口,各种短视频 App 如雨后春笋般先后上线,视频越来越像文字.图片一样,成为每一个 App 不可或缺的一部分. 1. 包体一定要尽可能小 如何做到尽可能的减小 S ...
随机推荐
- [11]APUE:(文件)记录锁
[a] 概念 建议锁:在遵循相同记录锁规则的进程间生效,通常用于保证某个程序自身多个进程间的数据一致性 强制锁:意在保证所有进程间的数据一致性,但不一定有效:如不能应对先 unlink 后建立同名副本 ...
- SQL Server 2008通过LinkServer操作ORACLE
时光荏苒~~ 最近项目有需求需要通过SQL Server2008中的数据自动更新到ORACLE中,其实,一开始肯定会想到触发器,因为可以保证实时性. 方案一: 首先,我很确定的一件事情就是MSSQL中 ...
- Oracle 11g 服务器安装图解
平常Oracle都是安装到本地的,没有安装到服务器过,今天找了个帖子是安装到服务器的图解 http://jingyan.baidu.com/album/948f5924373c04d80ff5f9f5 ...
- K/3 Cloud开发之旅--环境准备篇
K/3 Cloud是金蝶软件新推出的一款产品,介绍我就不多说了,谁用谁知道啊,那么我们如果要基于它做开发需要什么环境呢 开发环境必备软件 1 操作系统Windows X86/X64 或者Windows ...
- 《photon中配置lite的相关问题》
前几天在学习photon的时候发现了一个问题: 无论如何都找不到Lite文件夹,我是一个新手这也是写给那些新上手的朋友: 首先下载SDK以后配置完成后无论如何都找不到Lite文件夹和相关的Lite.d ...
- Oracle数据库备份 expdp/impdp导出导入命令
使用EXPDP和IMPDP时应该注意的事项: EXP和IMP是客户端工具程序,它们既可以在客户端使用,也可以在服务端使用. EXPDP和IMPDP是服务端的工具程序,他们只能在ORACLE服务端使用, ...
- js数组去重的三种方法
<script type="text/javascript"> /*// 第一种冒泡法删除 var arr=[1,2,2,78,3,456,456]; for(var ...
- ODBC,OLEDB,ADO,ADO.net,JDBC 理解
一 .ODBC 开放式数据库互联(Open Database connectivity), 93年微软推出的实现应用程序 和关系数据库直接 通讯的借口标准.只能用于关系数据库 . 注意事项 : 必须先 ...
- #ing# CSS细节注意点
目录: 常用简写 权重(优先级) Hack 常用简写 权重(优先级) Hack etc
- invalidate()和postInvalidate()的使用与区别
Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型: Android UI操作并不是线程安全的,并且这些操作必须在UI线程 ...