如何为编程爱好者设计一款好玩的智能硬件(九)——LCD1602点阵字符型液晶显示模块驱动封装(下)
2015-10-02 20:17
531 查看
六、温湿度传感器DHT11驱动封装(下):如何为编程爱好者设计一款好玩的智能硬件(六)——初尝试·把温湿度给收集了(下)!
七、点阵字符型液晶显示模块LCD1602驱动封装(上):如何为编程爱好者设计一款好玩的智能硬件(七)——LCD1602点阵字符型液晶显示模块驱动封装(上)
八、LCD1602点阵字符型液晶显示模块驱动封装(中):如何为编程爱好者设计一款好玩的智能硬件(八)——LCD1602点阵字符型液晶显示模块驱动封装(中)
九、LCD1602点阵字符型液晶显示模块驱动封装(下)
在上文中我们终于实现了一个简单版的无线滚动屏!本节对其工程进行详细讲解——
工程概述
keil u5 PK51IDE
无线显示屏采用蓝牙串口透传模块和LCD1602液晶显示模块
单片机采用STC89C51单片机
实现上位机通过串口助手发送一行msg,其在LCD屏上显示出来
要求msg长度小于32
更多详情请见前两节内容
1、LCD1602封装——LCD1602.C内部封装(一般不要改动)用的时候只需要根据平台重新修改.h内的宏定义即可
下面3个函数是基础通信函数,分别负责忙检测、写命令和写数据。具体细节可以参考——如何为编程爱好者设计一款好玩的智能硬件(七)——LCD1602点阵字符型液晶显示模块驱动封装(上))
下面的LCD1602初始化函数负责对LCD显示模式进行设置,如设置是否有光标、设置memory指针的方向...关于初始化为什么这样以及这些命令表示什么意思,可以参考——如何为编程爱好者设计一款好玩的智能硬件(七)——LCD1602点阵字符型液晶显示模块驱动封装(上))
下面是一些基于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点阵字符型液晶显示模块驱动封装(上))的内存映射和指令说明小节
2、LCD1602封装——LCD1602.h根据平台重新修改.h内的宏定义适应不同硬件平台
下面是根据AT89C52的平台特性对宏进行的修改,由于51单片机引脚操作比较简单,且支持读写,无需切换属性~因此下面部分宏定义的功能可以不定义~但是对于STM32就比较复杂了!正因如此,我STM32的封装也没想到一个比较好的处理方式,在我的工程里有基于STM32宏定义修改,不过存在问题,如果今后要用,一定要修改好!!!
3、工程整体逻辑简单梳理
main函数中不断检测串口是否发来有效数据(暂且把一行当为有效数据),一旦有效数据到来就调用ShowMessage显示出来~
串口中断是每收到一行置flag标志位为1,一旦point超过getByte大小就从0开始填充~
小结&接下来计划:
终于,我们把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点阵字符型液晶显示模块驱动封装(上)
八、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(5); LCD1602_WriteCom(0x38); LCD1602_DELAY_MS(5); LCD1602_WriteCom(0x38); LCD1602_DELAY_MS(5); LCD1602_WriteCom(0x38); LCD1602_WriteCom(0x08); /*display close*/ LCD1602_WriteCom(0x01); /*display clear*/ LCD1602_WriteCom(0x06); /*display cursor movement settings*/ LCD1602_DELAY_MS(5); 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(5); } void LCD1602_WriteChar(t_uc x,t_uc y,t_uc temp_data)//(x,y),data,ascill { if (y == 0)//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 == 0)//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)-1; if(from<0 || from>31 || to<0 || to>31)return;//shouldn't out the 32 datas if(to<16){//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>15){//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<16;i++){ LCD1602_WriteData(s[i]); LCD1602_DELAY_MS(delay_ms); } LCD1602_WriteCom(0xC0 + from); for(i=16;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^0; sbit sLCD1602_RW_PIN = P1^1; sbit sLCD1602_EN_PIN = P2^5; #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 (1) { //LCD1602_ShowMessage(0,"hello world! I'm beautifulzzzz.",1000); if(flag==1) { flag=0; SendStr(getByte); LCD1602_Clear(); LCD1602_ShowMessage(0,getByte,1000); } // 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 4 //串行中断服务程序 { if(RI){ //判断是接收中断产生 RI=0; //标志位清零 getByte[point]=SBUF; //读入缓冲区的值 if((point>0) && (getByte[point-1]==0x0d) && (getByte[point]==0x0a)){ getByte[point-1]=0x00; flag=1; point=0; }else{ point++; if(point==40){ point=0; } } } }
小结&接下来计划:
终于,我们把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 持续更新中~
相关文章推荐
- QT5 学习之路08---事件的接受与忽略
- IntelliJ IDEA 与 Gradle + Spring项目的初次尝试
- hdu1056 HangOver
- C#学习之路,学习笔记 2.3 ASCLL编码和Unicode编码
- 玩转Metasploit系列(第一集)
- python 弄github代码库列表
- 关于利用反射调用程序集中的函数属性的代码
- JavaAPI_4
- C++静态库与动态库
- lua转让C++书面DLL达到“热更新”
- 学习日志---treemap
- java自定义类加载器
- poj 算法基础 编程题#1:UNIMODAL PALINDROMIC DECOMPOSITIONS
- Java中equals方法与==和hashCode的区别
- Google C++ Style Guide的哲学
- Google C++ Style Guide的哲学
- JDK,JRE,JVM区别与联系
- java字符串与整数之间的互相转换
- PHP与Spring之间的强势接口设计:学习案例
- C++学习笔记之类模板