STM32实战应用(一)——1602蓝牙时钟1液晶的显示测试

前言

从51到STM32F4学习这么久了,总算找到点头绪了,目前学习了GPIO,中断,定时器,看门狗的基本使用,所以想试着看看能不能做个什么东西,就是想复习一下最近学习的知识。正好上学期单片机课程设计做过一个可以蓝牙、按键校准、带温度显示的时钟,所以我想看能不能将程序移植到STM32上呢?说做就做,经过三天的时间,几次的程序修改和调试,终于成功了!

关于51单片机实现的时钟可以参考我以前发表的博文,里面还有演示的视频链接

单片机课程设计——《基于AT89S52单片机和DS1302时钟芯片的电子时钟(可蓝牙校准)》

由于STM32内部定时器的精度还是很高的(一小时慢1s),所以就没有使用DS1302时钟芯片(关键是手里没有),显示上和课程设计做的有些不一样,没有增加日期和星期显示,就时间、闹钟和温度的显示。

今天先学习一下1602液晶的显示,那么如何用STM32控制LCD1602显示字符,字符串或数字呢?

1602液晶介绍

工业字符型液晶,能够同时显示16x02即32个字符。1602液晶也叫1602字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此所以它不能很好地显示图形(用自定义CGRAM,显示效果也不好)。市面上字符液晶大多数是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶。1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。

由于1602液晶是5V供电,引脚高电平为5v。不像51单片机IO输出高电平5v,STM32高电平只有3.3v,低电平0v,找到了1602的数据手册,里面居然没有说明高电平电压范围,到底能不能驱动呢?我又查找了1602驱动芯片HD44780的数据手册,其中有一个电压特性,如下图

可见用STM32的3.3v电平驱动显示完全没问题,看到这我就放心了,代码经过多次的修改后,终于成功显示了,所以还是要多看看数据手册。

硬件电路连接

程序设计

1.控制线宏定义,通过位带操作,以后就可以像51那样RS=1来操作了,是不是很熟悉呢?这里还将数据线的8个端口定义为了一个LCD_DB

#define LCD_RS PAout(1)
#define LCD_RW PAout(4)
#define LCD_EN PAout(6)
#define LCD_DB GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 |GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15

2.LCD相连的GPIO配置,将数据线端口配置为OD(开漏)输出模式,可以做双向IO使用,在检测LCD是否忙时,需要读取D7位的状态

void LCD_GPIO_Config(void)
{
    GPIO_InitTypeDef  IO_Init;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOE,ENABLE);

    /*控制线初始化 : */
    IO_Init.GPIO_Mode=GPIO_Mode_OUT;        //输出
    IO_Init.GPIO_OType=GPIO_OType_PP;        //推挽模式
    IO_Init.GPIO_Pin=GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_6;
    IO_Init.GPIO_PuPd=GPIO_PuPd_UP;            //
    IO_Init.GPIO_Speed=GPIO_Speed_2MHz;        //GPIO_Speed_2MHz
    GPIO_Init(GPIOA,&IO_Init);

    /*数据线初始化*/
    IO_Init.GPIO_Mode=GPIO_Mode_OUT;
    IO_Init.GPIO_OType=GPIO_OType_OD;        //开漏输出可双向
    IO_Init.GPIO_Pin=LCD_DB;
    IO_Init.GPIO_PuPd=GPIO_PuPd_UP;            //上拉
    IO_Init.GPIO_Speed=GPIO_Speed_2MHz;
    GPIO_Init(GPIOE,&IO_Init);
    /*测试 : 高电平3.3v
    LCD_RS=1;
    LCD_RW=1;
    LCD_EN=1;
    GPIO_SetBits(GPIOE,LCD_DB); */
}

3.实现P1=0xff功能的函数,带参数

void GPIO_OutData(u8 Dat)
{
    u16 tmp;
    tmp = 0;
    tmp =Dat;
    tmp <<= 8;            //数据左移到高8位
    GPIO_Write(GPIOE,tmp);        //数据写入到GPIOE高8位
}

4.检测LCD是否忙

void LCD_CheckBusy(void)
{
    u8 sta;
    GPIO_OutData(0xff);
    LCD_RS=0;
    LCD_RW=1;
    do{
        LCD_EN=1;
        delay_ms(5);
        sta = GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_15);
        LCD_EN =0;
    }while(sta & 0x80);
}

5.向LCD写一字节数据

/* LCD_RS = 1, LCD_RW = 0 */
void LCD_WriteData(u8 Dat)
{

    LCD_CheckBusy(); //忙则等待
    LCD_RS=1;
    LCD_RW=0;
    GPIO_OutData(Dat);
    LCD_EN=1;
    delay_ms(1);
    LCD_EN = 0;

}

6.向LCD写一字节命令

/*LCD_RS = 0, LCD_RW = 0*/
void LCD_WriteCmd(u8 Cmd)
{
    LCD_CheckBusy(); //忙则等待
    LCD_RS = 0;
    LCD_RW = 0;
    GPIO_OutData(Cmd);
    LCD_EN = 1;
    delay_ms(1);
    LCD_EN = 0;
}

7.LCD初始化

void LCD_Init(void)
{
    LCD_WriteCmd(0x38);
    LCD_WriteCmd(0x0C);
    LCD_WriteCmd(0x06);    /*显示光标移动设置*/    delay_ms(1);
    LCD_WriteCmd(0x01);    /*显示清屏*/
}

8.LCD清屏

void LCD_ClearScrren(void)
{
    LCD_WriteCmd(0x01);
}

9.根据xy坐标,写入对应的数据位置

void LCD_SetCursor(u8 x, u8 y)
{
    u8 addr;
    if (y == 0)
        addr = 0x00 + x;
    else
        addr = 0x40 + x;
    LCD_WriteCmd(addr | 0x80);
}

10.根据xy坐标显示一个字符

void LCD_DisChar(u8 x,u8 y,u8 ch)
{
    LCD_SetCursor(x,y);        //字符显示位置设定
    LCD_WriteData(ch);
}

11.显示两位的数字

void LCD_DisNumber(u8 x,u8 y,u8 Num)
{
    LCD_SetCursor(x,y);
    LCD_WriteData(0x30+Num/10);
    LCD_SetCursor(x+1,y);
    LCD_WriteData(0x30+Num%10);
}

12.显示字符串

void LCD_DisString(u8 x,u8 y,u8 *str)
{
    LCD_SetCursor(x, y);
    while(*str != ‘\0‘)
    {
        LCD_WriteData(*str++);
    }
}

主函数

int main(void)
{
    delay_init(168);
    LED_Init();

    LCD_GPIO_Config();
    LCD_Init();
    LCD_ClearScrren();
    while(1)
    {
        delay_ms(500);
        LED1_ON;
        LCD_DisString(0,0,"abcdefghijklmnop");
        delay_ms(500);
        LED1_OFF;
        LCD_DisNumber(0,1,56);
        LCD_DisChar(2,1,‘a‘);
        LCD_DisString(3,1," Hello World!");
    }
}

实际显示效果:

显示非常完美,和51驱动没有什么区别

总结:

实际运行时,不使用检测忙函数也行,1602显示正常了,接下来就是增加定时器显示时钟了。在设置IO口模式时,可以将模式设置为开漏模式,就可以实现双向IO的目的,即可输出,又可以读取外部输入。通过位带操作和宏定义就可以像51那样直接操作IO口输出高低电平了。

参考资料:

1602字符液晶_百度百科

HD44780器件手册

程序源码下载链接: https://pan.baidu.com/s/1hsvEBcg 密码: fk3b

欢迎查看我以前的单片机学习笔记:

STM32学习笔记(五)——通用定时器计数延时

STM32学习笔记(四)——串口控制LED(中断方式)

STM32学习笔记(三)——外部中断的使用

STM32学习笔记(二)——串口控制LED

STM32学习笔记(一)——点亮一个LED

单片机之模块化编程

基于51单片机IIC通信的PCF8591学习笔记

基于51单片机IIC通信的AT24C02学习笔记

以上是我学习过程的一些个人理解,有不对或不准确的地方,欢迎各位大神指正。

2017年4月23日14:24:45

时间: 2024-11-04 03:37:21

STM32实战应用(一)——1602蓝牙时钟1液晶的显示测试的相关文章

【单片机】时钟及温度的显示

回头看我所写的文章,基本都是软件方面的,是个典型的"欺软怕硬"的人.然而,在最开始的时候,我学习的是硬件.在前面文章<我的2013–一起从心开始>一文中写道,我在大一暑假的时候开始了单片机的学习,在大二.大三期间做过些小东西.刚进入程序员的领域的时候,显然是单片机带我入了门.下面我将写写用单片机做过的一些东西,权当纪念. 本文介绍我大一暑假学完单片机后,在大二上学期为参加学校星火杯而完成的作品(最终没有参加比赛).这个电子制作是关于用单片机显示时间的作品,其功能就用单片机控

STM32 液晶屏 显示字符串 中遇到的一个问题

用STM32控制液晶屏显示电流.电压参数. 我希望的结果是这样的: 可是,实际写出来的效果是这样的. 可以看出,电流参数那一行后面多出了几个字符"Volta",刚好是要下一行需要显示内容的前面一部分. 试着把电流参数值得位数改短一些,比如把前面的20.54改为2.54.显示出来就是正常的.由此想到这个问题的产生可能和要显示的字符串的长度有关.所以就把跟电流显示的相关的代码都看了看,从定义到调用液晶模块的API. char Current_display[15];// 定义一个与电流参数

[CXF REST标准实战系列] 二、Spring4.0 整合 CXF3.0,实现测试接口(转)

转自:[CXF REST标准实战系列] 二.Spring4.0 整合 CXF3.0,实现测试接口 文章Points: 1.介绍RESTful架构风格 2.Spring配置CXF 3.三层初设计,实现WebService接口层 4.撰写HTTPClient 客户端,并实现简单调用 介绍RESTful架构风格 REST是REST之父Roy Thomas创造的,当时提出来了REST的6个特点:客户端-服务器的.无状态的.可缓存的.统一接口.分层系统和按需编码.其具有跨语言和跨平台的优势. REST是一

sTM32 使用TIMx_CH1作为 Tx1F_ED 计数器时钟

环境:iar arm 5.3 stm32f103vbt6 使用PA.8 外部输入10Mhz的方波.可从systick中断得到数据4. 4×5000(预分频值)×1000(tick中断时间)=20MHz 属于双边沿检测,一个PA.8个脉冲有2个边沿,所以时钟加倍. 由于使用了TI1F_ED它的结构如下: void RCC_Configuration( void ) { /* Setup STM32 system (clock, PLL and Flash configuration) */ Sys

STM32学习笔记10(实时时钟RTC)

对于单片机转ARM的同学来说,RTC可能比较少接触.提到实时时钟,更经常想到的是DS1302.当然,在STM32里,自己一个CPU已经足够,不需要DS1302. 实际上,RTC就只一个定时器而已,掉电之后所有信息都会丢失,因此我们需要找一个地方来存储这些信息,于是就找到了备份寄存器.因为它掉电后仍然可以通过纽扣电池供电,所以能时刻保存这些数据.我们在本期教程中将详细讲述RTC原理及例程,以引导大家顺利进入RTC的世界. 1.STM32的RTC模块 RTC模块之所以具有实时时钟功能,是因为它内部维

STM32之USART1串口:蓝牙接收字符控制LED亮灭

基础的就不讲了,直接上配置文件,led.c  led.h  usart.c  usart.h  stm32f10x_it.c   延时函数这些都自己写吧,网上搜索一大把,本次用到的蓝牙模块为 不知什么系列,具体见文末图,蓝牙的RXD连接单片机的TXD,蓝牙的TXD连接单片机的RXD,还有两个口,VCC和GND,接5V电源,还有配套自己写的安卓app,文末贴上百度网盘下载地址,实现的功能就是手机蓝牙app里面发送'A'字符到单片机灯亮,发送'B'字符灯灭: led.c文件所包含的内容: void

STM32 CubeMX 中如何查看系统时钟

uint32_t sysclock = 0; sysclock = HAL_RCC_GetSysClockFreq(); 这样就可以在线仿真时看sysclock了,这些函数都在rcc这个库里面,还可以查看时钟树上其他总线上的时钟.

STM32 STOP模式唤醒后的时钟

进了STOP模式后,PLL停掉了,所以,如果开始的时钟配置,用的是PLL,那么唤醒后,需要重新配置RCC. 如果使用的是PLL,及时是用MSI作为时钟源,放大出来的,比如4M的MSI,PLL放大到48M,或者8M,STOP模式唤醒后,还是得重新配置时钟,因为用的是PLL. 如果为了节省时间,想退出STOP模式后,不用重新配置RCC(配置RCC,如果是外部HSE,耗时大概1.2ms),可以考虑用MSI STOP模式唤醒后 The MSI oscillator is selected as syst

[CXF REST标准实战系列] 二、Spring4.0 整合 CXF3.0,实现测试接口

Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Reprint it anywhere u want. 文章Points: 1.介绍RESTful架构风格 2.Spring配置CXF 3.三层初设计,实现WebService接口层 4.撰写HTTPClient 客户端,并实现简单调用 介绍RESTful架构风格 REST是REST之父Roy Thomas创造的,当时提出来了REST的6个特点:客户端-服务器的.无状态的.可缓存的.统一接口.分层系