STM8系列单片机用4线LCD1602驱动程序(完整源码)
金坷居士2016/04/29软件综合 IP:澳大利亚
uouSTM8是一种性价比很高的单片机,LCD1602是很常用的电子制作零件,当这两者组合的时候,会发现LCD1602把STM8S103的GPIO基本都占掉了。
标准模式下LCD1602需要8个数据线(DB0-DB7)3个辅助信号线(RW RS E),这就11个GPIO的需求量,而20脚的STM8被占了11个IO之后就基本不能干啥了
好在LCD1602还有4线驱动模式,如果把检测忙和读LCD1602内部寄存器的功能省略掉,那就只需要6跟线(DB4 - DB7 RS E)


此时就木有读LCD1602的操作了,等待LCD忙完的功能由一个延时函数代替
写LCD1602时,首先等待会儿LCD忙完,然后如果是写指令那么RS=0,写数据RS=1。4线写数据的时候,先写高4位,再写低4位,每次写完之后需要在E上产生一个上升沿信号。


LCD1602在使用之前需要先初始化,根据LCD1602的PDF,先发3个0x03(DB4-DB7=0x03)再发1个0x02,最后发0x28,然后这样就进入4线模式了,之后的使用方法和8线的差不多了
0x01清屏
0x80和0xC0分别是两行的开始地址,将字符的序号加上行的地址作为命令发送给LCD1602会让下一个字符输出在指定的位置
下面是LCD1602.C

<code class="lang-cpp">#include "main.h"
  
  
void LCD_Init(void){
    GPIO_PinInit(RS_PORT    ,RS_PIN ,GPIO_MODE_OUT_PP_HIGH_FAST);
    GPIO_PinInit(E_PORT,E_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);
    GPIO_PinInit(DB7_PORT,DB7_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);
    GPIO_PinInit(DB6_PORT,DB6_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);
    GPIO_PinInit(DB5_PORT,DB5_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);
    GPIO_PinInit(DB4_PORT,DB4_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);  
      
    Util_DelayUs(1000);
      
    LCD_Write(0,0x33);
    LCD_Write(0,0x32);
    LCD_Write(0,0x28);           
    LCD_Write(0,0x0c);
    LCD_Write(0,0x01);  
    LCD_Write(0,0x80);  
}
  
  
void LCD_Write(unsigned char isData,unsigned char cmd){
    Util_DelayUs(2000); //Hardcoding delay, keep waiting while the LCD is busy
      
  
    GPIO_Pin(RS_PORT, RS_PIN, isData);
    GPIO_PinClr(E_PORT, E_PIN);
  
  
    GPIO_Pin(DB7_PORT, DB7_PIN, BitGet(cmd, 7));
    GPIO_Pin(DB6_PORT, DB6_PIN, BitGet(cmd, 6));
    GPIO_Pin(DB5_PORT, DB5_PIN, BitGet(cmd, 5));
    GPIO_Pin(DB4_PORT, DB4_PIN, BitGet(cmd, 4));
    nop();
    nop();
    GPIO_PinSet(E_PORT, E_PIN);     //E = 1
    nop();
    nop();
    GPIO_PinClr(E_PORT, E_PIN);     //E = 0
  
  
    GPIO_Pin(DB7_PORT, DB7_PIN, BitGet(cmd, 3));
    GPIO_Pin(DB6_PORT, DB6_PIN, BitGet(cmd, 2));
    GPIO_Pin(DB5_PORT, DB5_PIN, BitGet(cmd, 1));
    GPIO_Pin(DB4_PORT, DB4_PIN, BitGet(cmd, 0)); 
    nop();
    nop();
    GPIO_PinSet(E_PORT, E_PIN);     //E = 1
    nop();
    nop();
    GPIO_PinClr(E_PORT, E_PIN);     //E = 0
}
  
void LCD_Locate(unsigned char x,unsigned char y){ 
    LCD_Write(0, x + (y?0xc0:0x80));    
} 
  
void LCD_PrintString(char* c){
    while(*c){
        LCD_Write(1,*c);
        c++;
    }
}</code>
main.h中定义了一些宏:

这些是函数包装好的声名,直接用就好,用之前先初始化
这个main.h还包含一些通用函数,比如#define版本的GPIO操作,省得跳转到库函数去了,能提高点效率(有待考证)
<code class="lang-cpp">#ifndef __MAIN_H__
#define __MAIN_H__
  
#include "stm8s.h"
#include "GPIODef.h"
  
//Util Macros
#define NULL 0
#define Pin(p) (1<<p) #define bitget(bit, i) ((bit>>i)&1)
#define GPIO_PinSet(GPIOx, pin) SetBit(GPIOx->ODR, pin)
#define GPIO_PinClr(GPIOx, pin) ClrBit(GPIOx->ODR, pin)
#define GPIO_PinGet(GPIOx, pin) BitGet(GPIOx->IDR, pin)
#define GPIO_Pin(GPIOx, pin, v) if(v){SetBit(GPIOx->ODR, pin);}else{ClrBit(GPIOx->ODR, pin);}
#define GPIO_PinInit(GPIOx, pin, mode) GPIO_Init(GPIOx, 1<<pin, mode)    lcd1602 #define lcd_clear() lcd_write(0,0x01) void lcd_init(void); lcd_write(unsigned char isdata,unsigned cmd); lcd_locate(unsigned x,unsigned y); lcd_printstring(char* c); util functions util_delay(unsigned int a); #endif< code></pin,></p)></code>



延时函数:
<code class="lang-cpp">void Util_Delay(unsigned int a){
    while(a--);
}</code>


延时函数是在CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);情况下的,如果CPU的时钟配置不一样,延时的时间也不一样


LCD1602等待忙那里宁可多等也不能少等,等少了根本不能用,如果觉得等待浪费效率的话,那就接上RW线做Busy检测吧,代码不贴了,因为懒没做
另外在单片机上点之后也不要立刻就开始初始化屏幕,需要等电压稳定下再来
以上程序完全原创,开发环境STVD+COSMIC,使用ST官方库函数






LCD1602是能打出日文假名的,比如
<code class="lang-cpp">LCD_Write(1,0xC1);
LCD_Write(1,0xD9); 
LCD_Write(1,0xC9);</code>
就会打出琪露诺的日文名

特殊符号比如欧姆,mu等也能打出来,具体参见PDF
attachment icon LCD1602.pdf 842.43KB PDF 198次下载 预览
来自:计算机科学 / 软件综合
11
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
金坷居士 作者
8年8个月前 IP:澳大利亚
817881
引用 phpskycn:
ST的I2C威名远扬……慎重使用,除非对存在的问题很了解并且愿意花时间绕过
窝的I2C倒是能调的通、没有传说中辣么巨毒
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
金坷居士作者
8年8个月前 IP:澳大利亚
818243
引用 phpskycn:
试了下I2C和MPU6050通信,能工作但是有一定概率会卡住,重新上电又能解决
窝那个是驱动24C02,没问题的,可能是ST的I2C兼容性不好
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
所属分类
上级专业
同级专业
金坷居士
学者 机友 笔友
文章
170
回复
1711
学术分
11
2011/09/23注册,3个月5天前活动

怪哉!灵异的三极管电流流向! 这素一个在仿真的RCC电路,示波器上绿色的是集电极电流红色的是发射极电流。窝萌都知道发射姬电流素集电极电流和基极电流之和,所以讲道理发射极电流一定比集电极略大。可仿真结果刷了三观,Q1集电极电流一部分流经基极,然后流经Q2的C->E。

主体类型:个人
所属领域:无
认证方式:手机号
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}