完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
在上文中我们终于实现了一个简单版的无线滚动屏!本节对其工程进行详细讲解——
工程概述 keil u5 PK51IDE 无线显示屏采用蓝牙串口透传模块和LCD1602液晶显示模块 单片机采用STC89C51单片机 实现上位机通过串口助手发送一行msg,其在LCD屏上显示出来 要求msg长度小于32 更多详情请见前两节内容 1、LCD1602封装——LCD1602.C内部封装(一般不要改动)用的时候只需要根据平台重新修改.h内的宏定义即可 下面3个函数是基础通信函数,分别负责忙检测、写命令和写数据。具体细节可以参考 1 //------------------------------------------------ 2 //base communite function 3 t_uc LCD1602_CheckBusy(void)//check busy 4 { 5 t_c temp_data; 6 LCD1602_DATA_PORT_WRITE(0xFF); 7 LCD1602_RS_PIN_CLEAR; 8 LCD1602_RW_PIN_SET; 9 LCD1602_EN_PIN_CLEAR; 10 LCD1602_NOP; 11 LCD1602_EN_PIN_SET; 12 LCD1602_DATA_PORT_READ(&temp_data); 13 return (temp_data & 0x80); 14 } 15 16 void LCD1602_WriteCom(t_uc com)//write command 17 { 18 while(LCD1602_CheckBusy()); //if busy wait 19 LCD1602_RS_PIN_CLEAR; 20 LCD1602_RW_PIN_CLEAR; 21 LCD1602_EN_PIN_SET; 22 LCD1602_DATA_PORT_WRITE(com); 23 LCD1602_NOP; 24 LCD1602_EN_PIN_CLEAR; 25 } 26 27 void LCD1602_WriteData(t_uc temp_data)//write data 28 { 29 while(LCD1602_CheckBusy()); //if busy wait 30 LCD1602_RS_PIN_SET; 31 LCD1602_RW_PIN_CLEAR; 32 LCD1602_EN_PIN_SET; 33 LCD1602_DATA_PORT_WRITE(temp_data); 34 LCD1602_NOP; 35 LCD1602_EN_PIN_CLEAR; 36 } 下面的LCD1602初始化函数负责对LCD显示模式进行设置,如设置是否有光标、设置memory指针的方向...关于初始化为什么这样以及这些命令表示什么意思,可以参考——如何为编程爱好者设计一款好玩的智能硬件(七)——LCD1602点阵字符型液晶显示模块驱动封装(上)) 1 //------------------------------------------------ 2 //initialization function 3 void LCD1602_Init(void) 4 { 5 LCD1602_WriteCom(0x38); /*display mode settings*/ 6 LCD1602_DELAY_MS(5); 7 LCD1602_WriteCom(0x38); 8 LCD1602_DELAY_MS(5); 9 LCD1602_WriteCom(0x38); 10 LCD1602_DELAY_MS(5); 11 LCD1602_WriteCom(0x38); 12 LCD1602_WriteCom(0x08); /*display close*/ 13 LCD1602_WriteCom(0x01); /*display clear*/ 14 LCD1602_WriteCom(0x06); /*display cursor movement settings*/ 15 LCD1602_DELAY_MS(5); 16 LCD1602_WriteCom(0x0C); /*display and cursor settings*/ 17 } 下面是一些基于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点阵字符型液晶显示模块驱动封装(上))的内存映射和指令说明小节 1 //------------------------------------------------ 2 //Function 3 void LCD1602_Clear(void)//clear screen 4 { 5 LCD1602_WriteCom(0x01); 6 LCD1602_DELAY_MS(5); 7 } 8 9 void LCD1602_WriteChar(t_uc x,t_uc y,t_uc temp_data)//(x,y),data,ascill 10 { 11 if (y == 0)//the first line 12 { 13 LCD1602_WriteCom(0x80 + x); 14 } 15 else//the second line 16 { 17 LCD1602_WriteCom(0xC0 + x); 18 } 19 LCD1602_WriteData(temp_data); 20 } 21 22 void LCD1602_WriteString(t_uc x,t_uc y,t_uc *s)//(x,y),string data 23 { 24 if (y == 0)//the first line 25 { 26 LCD1602_WriteCom(0x80 + x); 27 } 28 else//the second line 29 { 30 LCD1602_WriteCom(0xC0 + x); 31 } 32 while (*s) 33 { 34 LCD1602_WriteData( *s); 35 s ++; 36 } 37 } 38 39 void LCD1602_ShowMessage(t_uc from,t_uc *s,t_uc delay_ms)//from(0~31),msg,each char delay time 40 { 41 t_uc i; 42 t_uc to=from+strlen((t_c*)s)-1; 43 if(from《0 || from》31 || to《0 || to》31)return;//shouldn‘t out the 32 datas 44 if(to《16){//only the first line 45 LCD1602_WriteCom(0x80 + from); 46 for(i=from;i《=to;i++){ 47 LCD1602_WriteData(s[i]); 48 LCD1602_DELAY_MS(delay_ms); 49 } 50 }else if(from》15){//only the sencond line 51 LCD1602_WriteCom(0xC0 + from); 52 for(i=from;i《=to;i++){ 53 LCD1602_WriteData(s[i]); 54 LCD1602_DELAY_MS(delay_ms); 55 } 56 }else{//both lines 57 LCD1602_WriteCom(0x80 + from); 58 for(i=from;i《16;i++){ 59 LCD1602_WriteData(s[i]); 60 LCD1602_DELAY_MS(delay_ms); 61 } 62 LCD1602_WriteCom(0xC0 + from); 63 for(i=16;i《=to;i++){ 64 LCD1602_WriteData(s[i]); 65 LCD1602_DELAY_MS(delay_ms); 66 } 67 } 68 } 2、LCD1602封装——LCD1602.h根据平台重新修改.h内的宏定义适应不同硬件平台 下面是根据AT89C52的平台特性对宏进行的修改,由于51单片机引脚操作比较简单,且支持读写,无需切换属性~因此下面部分宏定义的功能可以不定义~但是对于STM32就比较复杂了!正因如此,我STM32的封装也没想到一个比较好的处理方式,在我的工程里有基于STM32宏定义修改,不过存在问题,如果今后要用,一定要修改好!!! 1 #define MCU_AT89C52 2 3 // 4 //MCU_AT89C52 5 // 6 #ifdef MCU_AT89C52 7 8 #include “FUNC/delay.h” 9 #include 《intrins.h》 10 #include 《string.h》 11 12 //some typedef need to do 13 typedef unsigned char t_uc; 14 typedef unsigned short t_us; 15 typedef unsigned int t_ui; 16 typedef char t_c; 17 typedef short t_s; 18 typedef int t_i; 19 20 ***it sLCD1602_RS_PIN = P1^0; 21 ***it sLCD1602_RW_PIN = P1^1; 22 ***it sLCD1602_EN_PIN = P2^5; 23 24 25 #define LCD1602_DELAY_MS(x) DelayMs((x)) 26 #define LCD1602_NOP _nop_() 27 28 29 #define LCD1602_RS_PIN sLCD1602_RS_PIN 30 #define LCD1602_RS_PIN_SET LCD1602_RS_PIN=1 31 #define LCD1602_RS_PIN_CLEAR LCD1602_RS_PIN=0 32 #define LCD1602_RS_PIN_OUT 33 34 #define LCD1602_RW_PIN sLCD1602_RW_PIN 35 #define LCD1602_RW_PIN_SET LCD1602_RW_PIN=1 36 #define LCD1602_RW_PIN_CLEAR LCD1602_RW_PIN=0 37 #define LCD1602_RW_PIN_OUT 38 39 #define LCD1602_EN_PIN sLCD1602_EN_PIN 40 #define LCD1602_EN_PIN_SET LCD1602_EN_PIN=1 41 #define LCD1602_EN_PIN_CLEAR LCD1602_EN_PIN=0 42 #define LCD1602_EN_PIN_OUT 43 44 #define LCD1602_DATA_PORT_GPIO P0 45 #define LCD1602_DATA_PORT_IN 46 #define LCD1602_DATA_PORT_OUT 47 #define LCD1602_DATA_PORT_READ(x) (*(x))=LCD1602_DATA_PORT_GPIO 48 #define LCD1602_DATA_PORT_WRITE(x) LCD1602_DATA_PORT_GPIO=(x) 49 50 51 void LCD1602_WriteCom(t_uc com);//write command 52 void LCD1602_WriteData(t_uc temp_data);//write data 53 void LCD1602_Init(void);//initialization function 54 void LCD1602_Clear(void);//clear screen 55 void LCD1602_WriteChar(t_uc x,t_uc y,t_uc temp_data);//(x,y),data,ascill 56 void LCD1602_WriteString(t_uc x,t_uc y,t_uc *s);//(x,y),string data 57 void LCD1602_ShowMessage(t_uc from,t_uc *s,t_uc delay_ms);//from(0~31),msg,each char delay time 58 59 #endif 3、工程整体逻辑简单梳理 main函数中不断检测串口是否发来有效数据(暂且把一行当为有效数据),一旦有效数据到来就调用ShowMessage显示出来~ 1 /*------------------------------------------------ 2 主函数 3 ------------------------------------------------*/ 4 void main (void) 5 { 6 InitUART(); 7 LCD1602_Init(); 8 LCD1602_Clear();//ÇåÆÁ 9 while (1) 10 { 11 //LCD1602_ShowMessage(0,“hello world! I‘m beautifulzzzz.”,1000); 12 if(flag==1) 13 { 14 flag=0; 15 SendStr(getByte); 16 LCD1602_Clear(); 17 LCD1602_ShowMessage(0,getByte,1000); 18 } 19 // LCD1602_WriteChar(7, 0, ’o‘); 20 // LCD1602_WriteChar(8, 0, ’k‘); 21 // LCD1602_WriteString(3, 1, “Hard Work”); 22 //while(1); 23 } 24 } 串口中断是每收到一行置flag标志位为1,一旦point超过getByte大小就从0开始填充~ 1 /*------------------------------------------------ 2 串口中断程序 3 ------------------------------------------------*/ 4 void UART_SER (void) interrupt 4 //串行中断服务程序 5 { 6 if(RI){ //判断是接收中断产生 7 RI=0; //标志位清零 8 getByte[point]=SBUF; //读入缓冲区的值 9 if((point》0) && (getByte[point-1]==0x0d) && (getByte[point]==0x0a)){ 10 getByte[point-1]=0x00; 11 flag=1; 12 point=0; 13 }else{ 14 point++; 15 if(point==40){ 16 point=0; 17 } 18 } 19 } 20 } 小结&接下来计划: 终于,我们把LCD1602的驱动封装好了!并且修改了之前模块化模块的想法,引入新的设计方式——模块化功能组件的方式(功能组件一般有单片机、通信模块加传感器、显示器、按键或者机械装置组成)。 模块化模块:之前目标是对每个模块封装,使模块灵活适应各种组合(MCU+POWER+X1+X2+...) 模块化功能块:现在是分出基础部分(MCU+POWER+radio)+一个变动部分=构成功能块 因此,接下来我们将会涉足"X-OS"比较重要的一块——基础部分中的无线通信基础部分。而我们首先尝试的将是最赤裸的24L01无线2.4G通信模块驱动的封装!请持续关注~ |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1658 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1571 浏览 1 评论
998 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
695 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1617 浏览 2 评论
1876浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
663浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
528浏览 3评论
547浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
517浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-29 08:31 , Processed in 0.917913 second(s), Total 79, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号