打印
[其他ST产品]

STM32+12864实现RGB灯亮度的菜单调节

[复制链接]
1153|41
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
写在前面
这是我第一次写文章,可能有很多错误或者描述不到位的地方,**大家多多包涵。如果有前辈发现我的文章中有什么问题,欢迎指出,谢谢。同时,这篇文章也是用作我自己以后查询一些资料之用,所以我会分析很多的源码、协议等。不需要的朋友可以自行省略。程序上参考了野火和中景园的部分例程。

昨天,做了个小实验,使用STM32配合OLED12864实现对多个LED发光二极管的亮度管理。具体的要求如下:能够在OLED上显示出的LED的种类,如红灯、绿灯、蓝灯等。并在后面显示当前板子上对应的LED的实际亮度。利用两个按键进行调节。其中第一个按键用于选择LED,第二个按键实现对当前选中的LED的亮度进行调节。调节LED亮度的手段为PWM,调节的亮度等级为0-9。



使用特权

评论回复
评论
和下土 2023-9-29 18:55 回复TA
———————————————— 版权声明:本文为CSDN博主「lssylzb」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_41286749/article/details/103944033 
沙发
和下土|  楼主 | 2023-9-29 18:55 | 只看该作者
硬件方案
我使用了野火霸道V-2开发板,板上的芯片为STM32F103ZET6。板上外设搭载了一个RGB灯,可以分别控制红色、绿色、蓝色光的亮度。红、绿、蓝分别接在板子的PB5、PB0、PB1引脚。原理图如下:

使用特权

评论回复
板凳
和下土|  楼主 | 2023-9-29 18:55 | 只看该作者

使用特权

评论回复
地板
和下土|  楼主 | 2023-9-29 18:56 | 只看该作者
12864采用了OLED的版本,支持SPI通讯协议。

使用特权

评论回复
5
和下土|  楼主 | 2023-9-29 18:56 | 只看该作者
SPI通讯协议
SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。最早由摩托罗拉公司提出,是一种高速的,全双工,同步的通信总线。现广泛的用于ADC、LCD等设备。

使用特权

评论回复
6
和下土|  楼主 | 2023-9-29 18:56 | 只看该作者
SPI的优缺点:
优点:1.传输速度快
      2.用4条线完成数据传输,节约芯片管脚
缺点:1没有指定的流控制,没有应答机制确认是否接收到数据

使用特权

评论回复
7
和下土|  楼主 | 2023-9-29 18:56 | 只看该作者
SPI的硬件组成
SPI由四条数据线组成:
1.SCK:时钟线,由主机控制
2.MISO: M代表主机,I代表INPUT,S代表从机,O代表OUTPUT,即主收从发数据线
3.MOSI: M代表主机,O代表OUTPUT,S代表从机,I代表INPUT,即主发从收数据线
4.CS:片选信号线。0代表被选中,1代表没被选中

使用特权

评论回复
8
和下土|  楼主 | 2023-9-29 18:56 | 只看该作者
关于SPI协议本文只做基本的介绍,更多详细的了解大家可以在CSDN上查找其他的笔记,也可以在b 站搜索SPI协议,查找相关视频进行学习。

使用特权

评论回复
9
和下土|  楼主 | 2023-9-29 18:57 | 只看该作者
12864显示屏
12864简介
12864显示屏是一种统称,并非指专门的某一型号的显示屏。12864代表的含义是横向有128个像素,纵向有64个像素,即128*64大小的液晶屏。类似的命明规则包括1602(16代表一行可以显示16个字符,02表示有两行),1601(16代表一行可以显示16个字符,01表示有一行)等。不同的厂商生产的12864具体的使用方法可能不同,所以需要大家注意。

使用特权

评论回复
10
和下土|  楼主 | 2023-9-29 18:57 | 只看该作者
OLED12864简介
我选用的12864是OLED12864,没有带字库,所以需要我们利用取模软件对汉字进行取模后,才可以显示出汉字。12864支持SPI协议。可以利用SPI协议进行写入。与标准的SPI协议不同,我们只需要主机发送数据到OLED12864上即可。而且在SPI总线上只挂载了一个外设,所以我们将CS线硬件接地,保持选中状态。所以,我们实际上只使用了SPI协议中的MOSI线和SCLK线。由于我的PCB板上的丝印分别对应的接口为SDA和SCL,所以我在程序中使用了SDA和SCL来表示。OLED12864上还有两个接口,分别为RES和D/C,RES用于OLED的重置,D/C线用于控制向OLED12864发送的是命令还是数据。

使用特权

评论回复
11
和下土|  楼主 | 2023-9-29 18:57 | 只看该作者
OLED12864的控制
要想控制好12864,首先需要查阅其数据手册。根据数据手册可以得知,在每次使用OLED12864之前,首先需要对屏幕进行初始化。而对屏幕初始化则需要使用SPI协议进行数据传输,所以,我首先分析如何使用SPI进行数据传输。需要说明的是,我采用了ARM软件模拟的方法实现SPI传输,没有使用STM32的片上外设。

使用特权

评论回复
12
和下土|  楼主 | 2023-9-29 18:57 | 只看该作者
void OLED_WR_Byte(uint8_t dat,uint8_t cmd)
{       
        u8 i;                          
        if(cmd)
          OLED_DC_GPIO_DATA;
        else
          OLED_DC_GPIO_COM;
       
        for(i=0;i<8;i++)
        {
                OLED_SCLK_Clr();
                if(dat&0x80)
                   OLED_SDA_HIGH;
                else
                   OLED_SDA_LOW;
                OLED_SCLK_Set();
                dat<<=1;   
        }                                                   

        OLED_DC_GPIO_DATA;
e}            

使用特权

评论回复
13
和下土|  楼主 | 2023-9-29 18:57 | 只看该作者
这个自定义函数模拟了SPI协议,用于向 OLED12864发送数据。其中第一个形参用于填写发送数据的具体值。第二个形参用与选择发送的是数据,还是指令。所谓数据,大家可以理解为需要写入的十六进制数,而指令,则可以理解为当把数据写入oled的显存中后,让其显示出来。接下来,我们简单分析一下这个函数的具体实现原理。根据OLED12864的数据手册可知。当D/C线接为高电平时,代表向OLED12864写入数据,D/C线为低电平时写入指令。当调用该函数的时候,程序首先读取第二个形参com的数据。根据com形参的值,选择D/C线的值。OLED_DC_GPIO_DATA; 和 OLED_DC_GPIO_COM;两句我在头文件中定义。

使用特权

评论回复
14
和下土|  楼主 | 2023-9-29 18:58 | 只看该作者
选择好发送是数据还是指令。接下来就要发送形参1data中储存的具体的值,输输入的值一般为8bit。根据SPI协议,OLED12864在时钟线上升沿时接收数据。所以,我们首先调用OLED_SCLK_Clr();拉低时钟线。接下来是SPI发送的核心。0x80转化为二进制数为10000000(b),将我们要发送的数据和1000000(b)做与运算之后,就可以需要发送数据的最高位写的是0还是1.如果最高位为0,则SDA线发送低电平,代表逻辑0,反之,发送高电平,代表逻辑1。发送完数据后,拉高时钟线,产生一个上升沿。使OLED12864读取数据。这一个过程,完成了一个bit的发送。发送完一个bit的数据。将bata中的值左移一位。在重复上面的过程。一次需要发送8个bit即要重复8次上述过程。所以,我们将该部分程序放在for循环中。实现一个字节(8bit)数据的发送。

使用特权

评论回复
15
和下土|  楼主 | 2023-9-29 18:58 | 只看该作者
利用该函数,我们就可以向OLED12864写入数据或指令,实现OLED12864的控制。

使用特权

评论回复
16
和下土|  楼主 | 2023-9-29 18:59 | 只看该作者
OLED12864内容显示
在程序的最开始,定义了一个二维数据,用于存放OLED12864每一个点上的内容。可以理解为OLED12864的显存。

uint8_t OLED_GRAM[128][8];

使用特权

评论回复
17
和下土|  楼主 | 2023-9-29 18:59 | 只看该作者
这个二维数组的定义和其采用的主控有关。下面引用一下数据手册的内容。

使用特权

评论回复
18
和下土|  楼主 | 2023-9-29 18:59 | 只看该作者
本屏所用的驱动 IC 为 SSD1306;其具有内部升压功能;所以在设计的时候不需要再专一设计 升压电路;当然了本屏也可以选用外部升压,具体的请详查数据手册。SSD1306 的每页包含了 128 个字节,总共 8 页,这样刚好是 12864 的点阵大小。

使用特权

评论回复
19
和下土|  楼主 | 2023-9-29 18:59 | 只看该作者
驱动IC内部把OLED12864横向的64个像素点,以8个为一组,分成8组。每一组中纵向有128列。在讲解OLED12864控制时讲过,我们每次发送数据是8bit为一个单位进行传输。之所以这样设计,和内部IC驱动将其分为8组,每一组中有8个bit是相关的。也就是说,我们想要在OLED上显示内容,只需要把我们想显示的内容写入在OLED_GRAM[128][8]数组。在将数组中的值一次发送到驱动IC即可。接下来介绍将数组的数据发送到驱动IC的函数。

使用特权

评论回复
20
和下土|  楼主 | 2023-9-29 18:59 | 只看该作者
void OLED_Refresh(void)
{
        u8 i,n;
        for(i=0;i<8;i++)
        {
           OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
           OLED_WR_Byte(0x00,OLED_CMD);   //设置低列起始地址
           OLED_WR_Byte(0x10,OLED_CMD);   //设置高列起始地址
           for(n=0;n<128;n++)
                 OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
  }
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

103

主题

1067

帖子

0

粉丝