前言
在学习的过程中,发现许多代码都是在套用模板,但是修改模板的过程对新手是很不友好的
准备工作
外设连接
GND-----GND
VCC–3.3V
SCL----SCL
SDA----SDA
这个基本不会出错,就是一条时钟线,一条数据线,
cubemx的配置
这个挺简单的,动动手就好了(可以调为快速模式)
iic的传输原理
iic原理也很好懂我们只需要明白一个就是在传输中:SCL低电平时,SDA变化;SCL高电平时,从机读取SDA的电平(高为1,低为0),以及每发送一个ack的应答信号。具体如何编写,若简单的我们可以读参考手册(其实就是一些首发指令),难的还是建议从模板去修改
!!!记得看一下自己设备的地址,一般是是七位地址,但是因为一字节是八位bit,故习惯向左移一位,第0位的数据用于区分读指令or写指令
当然HAL库已经给我们写好了收发的函数,我们只需要懂得如何用就好
oled的显示原理
如图
我们实际上是通过向驱动芯片发指令来控制oled屏的亮灭
划分页的目的就是让我们通过一字节的数据去控制该页的那一列的显示
若向第0页的第三列写入0xC1(1100 0001),则
两种通讯,一种为指令另一种为数据
指令 : 0x7A(地址) 0x00 0xXX
页地址:高四位为B不变第四位则为我们要设置的页数,
既发送0x7A 0x00 0xB0;
列地址:若要设置为第90列(0x5A),则发送0x0A为低四位地址,0x15为高四位地址;
既发送 0x7A 0x00 0x0A 0x15
数据: 0x7A 0x40 0x01…
并且设置完一个字节后,列地址会自动加一,加到128列后页地址也会自动加一
列地址的第零列低四位地址为0x02
代码的设计
编写oled.c函数
根据上面的内容,我们写下发起通讯的函数(地址的话HAL库会帮我们发送的)
#define OLED_ADDRESSS 0x78
void OLED_TransmitByte(uint8_t data, OLED_TransmitMode mode) {
uint8_t send_buf[2] = { 0 };
if (mode)
send_buf[0] = 0x40;
else
send_buf[0] = 0x00;
send_buf[1] = data;
HAL_I2C_Master_Transmit(&hi2c1, OLED_ADDRESS, send_buf, 2, 1);
}
以及初始化函数(这个就是根据别的模板稍作修改)
/**
* @brief 初始化OLED屏幕
*/
void OLED_Init(void) {
OLED_TransmitByte(0xAE, OLED_TRANSMIT_CMD); /*display off*/
OLED_TransmitByte(0x02, OLED_TRANSMIT_CMD); /*set lower column address*/
OLED_TransmitByte(0x10, OLED_TRANSMIT_CMD); /*set higher column address*/
OLED_TransmitByte(0x40, OLED_TRANSMIT_CMD); /*set display start line*/
OLED_TransmitByte(0xB0, OLED_TRANSMIT_CMD); /*set page address*/
OLED_TransmitByte(0x81, OLED_TRANSMIT_CMD); /*contract control*/
OLED_TransmitByte(0xcf, OLED_TRANSMIT_CMD); /*128*/
OLED_TransmitByte(0xA1, OLED_TRANSMIT_CMD); /*set segment remap*/
OLED_TransmitByte(0xA6, OLED_TRANSMIT_CMD); /*normal / reverse*/
OLED_TransmitByte(0xA8, OLED_TRANSMIT_CMD); /*multiplex ratio*/
OLED_TransmitByte(0x3F, OLED_TRANSMIT_CMD); /*duty = 1/64*/
OLED_TransmitByte(0xad, OLED_TRANSMIT_CMD); /*set charge pump enable*/
OLED_TransmitByte(0x8b, OLED_TRANSMIT_CMD); /* 0x8B 内供 VCC */
OLED_TransmitByte(0x33, OLED_TRANSMIT_CMD); /*0X30---0X33 set VPP 9V */
OLED_TransmitByte(0xC8, OLED_TRANSMIT_CMD); /*Com scan direction*/
OLED_TransmitByte(0xD3, OLED_TRANSMIT_CMD); /*set display offset*/
OLED_TransmitByte(0x00, OLED_TRANSMIT_CMD); /* 0x20 */
OLED_TransmitByte(0xD5, OLED_TRANSMIT_CMD); /*set osc division*/
OLED_TransmitByte(0x80, OLED_TRANSMIT_CMD);
OLED_TransmitByte(0xD9, OLED_TRANSMIT_CMD); /*set pre-charge period*/
OLED_TransmitByte(0x1f, OLED_TRANSMIT_CMD); /*0x22*/
OLED_TransmitByte(0xDA, OLED_TRANSMIT_CMD); /*set COM pins*/
OLED_TransmitByte(0x12, OLED_TRANSMIT_CMD);
OLED_TransmitByte(0xdb, OLED_TRANSMIT_CMD); /*set vcomh*/
OLED_TransmitByte(0x40, OLED_TRANSMIT_CMD);
OLED_ClearBuffer();
OLED_Refresh();
OLED_TransmitByte(0xAF, OLED_TRANSMIT_CMD); /*display ON*/
}
其中修改模板最重要的便是这个宏定义的地址,以及这个发送通讯的参数是否于我们所使用的的相同,如果不同更改即可。
修改模板首先我们要检查一下,函数参数是否与头文件的函数声明一致,接下来再看变量的声明,一个好的代码必须具备很高的可移植性,所以在c文件中我们一定会用到枚举,结构体等知识,所以务必学好这方面的内容再来学习stm32
完整的资源我放在下面了,读者只需要下载,然后做完更改之后,将c文件放入Core/Src文件及 H文件放入CoreInc文件夹里就好
链接: 模板代码
模板如何使用
这份模板里面对使用做了详细的介绍,只提几句:
1.更改完设备地址的宏定义,以及HAL_I2C_Master_Transmit()的句柄后即可直接使用
2.若要使用取模则可以使用这个地址:链接: 取模地址
3.取模完之后记得去font.h里面重新声明一下(extern xxxx)
在font.h文件中
在font.c文件中,复制取模的代码
4.这个字符串是可以直接写字进去的例如:
第一个是x坐标,第二个是y坐标,第三个是显示的字符串(也可以写“狐狸小豆,Hello”),第四个是颜色。
但是我们取模只需要取汉字的就ok,这个是汉字(UTF-8)与ACSII码共用的,至于原理的话小伙伴们只需要看一下这个结构体的声明便懂了
结尾
这套模板是我在看视频的时候发现的,作为小白,我们要多看看别人的视频和代码的设计思路,只看一个是远远不够的。例如上篇文章的超声波,我视频看了至少五六个,以及参考了很多代码,其中状态机这个设计思路是我认为最适合我们理解于吸收的(还有关于溢出的判断以及再加一个定时器用于定时触发超声波,再或者取平均值的判断就交给我们自己来探索了)