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

#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++;
    }
}
main.h中定义了一些宏:

这些是函数包装好的声名,直接用就好,用之前先初始化
这个main.h还包含一些通用函数,比如#define版本的GPIO操作,省得跳转到库函数去了,能提高点效率(有待考证)
#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)>



延时函数:
void Util_Delay(unsigned int a){
    while(a--);
}


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


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






LCD1602是能打出日文假名的,比如
LCD_Write(1,0xC1);
LCD_Write(1,0xD9); 
LCD_Write(1,0xC9);
就会打出琪露诺的日文名

特殊符号比如欧姆,mu等也能打出来,具体参见PDF
attachment icon LCD1602.pdf 842.43KB PDF 199次下载 预览
来自:计算机科学 / 软件综合
11
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
我说要有光
8年9个月前 IP:河北
817712
标准的LCD1602似乎是日本字库,里面的"\"被"¥"代替
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
光谱
8年9个月前 IP:湖南
817719
引用 我说要有光:
标准的LCD1602似乎是日本字库,里面的"\"被"¥"代替
[s::D]试了两块1602, 一块是通常的牛屎,另一块是Hitachi的HD44780,\都显示为¥
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
光谱
8年9个月前 IP:湖南
817720
[s::dizzy:]前几天用STC12C2052AD&1602做了个温度计....就是用的6脚的驱动...
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
osfg
8年9个月前 IP:浙江
817813
前些时间我用105k4做过,当时初始化化很烦。后来先用八位指令写一遍初始化,再用4bit指令写一遍初始化才弄出来。到时我也分享下 搜狗截图20160430070654.png
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
drzzm32
8年9个月前 IP:陕西
817830
低IO数目的情况下可以试试IIC总线的屏,只占用两个IO。速度也不错,而且能比较容易地做多屏操作
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
phpskycn
8年9个月前 IP:浙江
817840
引用 drzzm32:
低IO数目的情况下可以试试IIC总线的屏,只占用两个IO。速度也不错,而且能比较容易地做多屏操作
ST的I2C威名远扬……慎重使用,除非对存在的问题很了解并且愿意花时间绕过
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
金坷居士作者
8年9个月前 IP:澳大利亚
817881
引用 phpskycn:
ST的I2C威名远扬……慎重使用,除非对存在的问题很了解并且愿意花时间绕过
窝的I2C倒是能调的通、没有传说中辣么巨毒
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
phpskycn
8年9个月前 IP:浙江
818166
引用 金坷居士:
窝的I2C倒是能调的通、没有传说中辣么巨毒
试了下I2C和MPU6050通信,能工作但是有一定概率会卡住,重新上电又能解决
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
金坷居士作者
8年9个月前 IP:澳大利亚
818243
引用 phpskycn:
试了下I2C和MPU6050通信,能工作但是有一定概率会卡住,重新上电又能解决
窝那个是驱动24C02,没问题的,可能是ST的I2C兼容性不好
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
1176764177
8年9个月前 IP:北京
818246
引用 金坷居士:
窝那个是驱动24C02,没问题的,可能是ST的I2C兼容性不好
我记得那个仅仅是stm32F1系列硬件iis不能开中断
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

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

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

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

主体类型:个人
所属领域:无
认证方式:手机号
IP归属地:未同步
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

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