万物基于点灯
——沃兹基硕德
点灯,I2C点灯
就像正常点灯一样,打开勘智IDE,大地球,礼物,find i2c,None。。。
果断下载GPIO,打开百度!
还是None?
自己动手!
API,I2C
翻开手册145页,大写的i2c映入眼前
> 145第14章集成电路内置总线(I²C)
API参考对应的头文件i2c.h为用户提供以下接口
• i2c_init
• i2c_init_as_slave
• i2c_send_data
• i2c_send_data_dma
• i2c_recv_data
• i2c_recv_data_dma
下单I2C_INIT,I2C_SEND_DATA,开始点灯!
码代码,堆积木
注册io6,io8 为i2c0地址线(可以使用ide一键配置,见ide使用)
ret += fpioa_set_function(6, FUNC_I2C0_SCLK);
ret += fpioa_set_function(8, FUNC_I2C0_SDA);
初始化I2C,配置I²C器件从地址、寄存器位宽度和I²C速率。
i2c_init(I2C_DEVICE_0, SSD1306_I2C_ADDR, 7, 400000);
问题出现了,ADDR地址多少?百度,0x78,完美,,,,,?恭喜你进入了第一个大坑
K210的SLK扫描不到最后一位地址——来自某热心群友的分享
折腾了一天一夜,最后祭出 MaixPy (MaixPy大法好)
i2c.scan()
>>>60
60=0x3c=0x78/2(RX78-2?不由自主幻视)
果然是有一位没读到。。
点灯!点1306!
打开1306手册,一堆文字。
果断关掉,打开百度打开maixpy,果然有现成 例程 (才发现这个例程已经给出addr地址 SSD1306_ADDR = 0x3c了,所以白忙活了一天?)
开始移植。。。1.。。2.。。3.。。。
移植好了
uint8 buff[2] = {0x00, 0x01};
void SSD1306_WriteCmd(uint8 cmd) {
buff[0] = 0x00;
buff[1] = cmd;
i2c_send_data(I2C_DEVICE_0, buff, 2); // cmd
// i2c_send_data(SSD1306_I2C_ADDR, cmd, 1);
}
void SSD1306_WriteData(uint8 data) {
buff[0] = 0x40;
buff[1] = data;
i2c_send_data(I2C_DEVICE_0, buff, 2); // cmd
}
// SSD1306初始化
void OLED_Init(void) {
// SSD1306复位之后,默认的是页寻址方式
SSD1306_WriteCmd(0xAE); //--display off
SSD1306_WriteCmd(0x00); //--set low column address
SSD1306_WriteCmd(0x10); //--set high column address
SSD1306_WriteCmd(0x40); //--set start line address
SSD1306_WriteCmd(0xB0); //--set page address
SSD1306_WriteCmd(0x81); // contract control
SSD1306_WriteCmd(0xFF); //--128
SSD1306_WriteCmd(0xA1); // set segment re-map 0 to 127
SSD1306_WriteCmd(0xA6); // set normal display
SSD1306_WriteCmd(0xA8); // set multiplex ratio(1 to 64)
SSD1306_WriteCmd(0x3F); //--1/32 duty
SSD1306_WriteCmd(0xC8); // Com scan direction
SSD1306_WriteCmd(0xD3); // set display offset
SSD1306_WriteCmd(0x00); // no offset
SSD1306_WriteCmd(0xD5); // set display clock divide ratio/oscillator
// frequency
SSD1306_WriteCmd(0x80); //
SSD1306_WriteCmd(0xD8); // set area color mode off
SSD1306_WriteCmd(0x05); //
SSD1306_WriteCmd(0xD9); // Set Pre-Charge Period
SSD1306_WriteCmd(0xF1); //
SSD1306_WriteCmd(0xDA); // set com pin hardware configuartion
SSD1306_WriteCmd(0x12); //
SSD1306_WriteCmd(0xDB); // set Vcomh
SSD1306_WriteCmd(0x30); // 0x20,0.77xVcc
SSD1306_WriteCmd(0x8D); // set charge pump enable
SSD1306_WriteCmd(0x14); //
SSD1306_WriteCmd(0xAF); //--turn on oled panel
}
//坐标设置:也就是在哪里显示
void OLED_SetPos(uint8 x, uint8 y) {
//以下3个寄存器只在页寻址的模式下有效
SSD1306_WriteCmd(0xb0 + y); //页地址设置 0xb0~0xb7
SSD1306_WriteCmd(((x & 0xf0) >> 4) | 0x10); //列高位地址设置
SSD1306_WriteCmd((x & 0x0f)); //列低位地址设置
}
//开启OLED显示
void OLED_DisplayOn(void) {
SSD1306_WriteCmd(0X8D); // SET DCDC命令
SSD1306_WriteCmd(0X14); // DCDC ON
SSD1306_WriteCmd(0XAF); // DISPLAY ON
}
//关闭OLED显示
void OLED_DisplayOff(void) {
SSD1306_WriteCmd(0X8D); // SET DCDC命令
SSD1306_WriteCmd(0X10); // DCDC OFF
SSD1306_WriteCmd(0XAE); // DISPLAY OFF
}
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样
void OLED_Clear(void) {
uint8 i, n;
for (i = 0; i < 8; i++) {
SSD1306_WriteCmd(0xb0 + i); //设置页地址(0~7)
SSD1306_WriteCmd(0x00); //设置显示位置—列低地址
SSD1306_WriteCmd(0x10); //设置显示位置—列高地址
for (n = 0; n < 128; n++) SSD1306_WriteData(0);
} //更新显示
}
好吧哪有那么无聊一个一个移植。这里使用的是freemote的 一文彻底了解SSD1306驱动0.96寸OLED
通过修改I2C的入口,绑定到K210的I2C上,代码就可以直接使用了(这才是写代码的好习惯,只需要修改入口,就可以轻松移植代码,而不是将代码与设备深度绑定,修改代码要从内部一点一点改)
修改方法如下,重写WriteCmd和WriteData
typedef __uint8_t uint8;
uint8 buff[2] = {0x00, 0x01};
void SSD1306_WriteCmd(uint8 cmd) {
buff[0] = 0x00;
buff[1] = cmd;
i2c_send_data(I2C_DEVICE_0, buff, 2); // cmd
// i2c_send_data(SSD1306_I2C_ADDR, cmd, 1);
}
void SSD1306_WriteData(uint8 data) {
buff[0] = 0x40;
buff[1] = data;
i2c_send_data(I2C_DEVICE_0, buff, 2); // cmd
}
void SSD1306_WriteData(uint8 data) {
buff[0] = 0x40;
buff[1] = data;
i2c_send_data(I2C_DEVICE_0, buff, 2); // cmd
}
入口修改好了,接下来就该点灯了。
测试!听从我的呼唤,闪烁吧,1306!
从maixpy移植oled_fill()进行测试:
void oled_fill(uint8 data) {
uint8 x, y;
for (x = 0; x < 8; x++) {
SSD1306_WriteCmd(0xb0 + x);
SSD1306_WriteCmd(0x10);
SSD1306_WriteCmd(0x01);
for (y = 0; y < 128; y++) {
SSD1306_WriteData(data);
}
}
}
主函数输入
i2c_init(I2C_DEVICE_0, SSD1306_I2C_ADDR, 7, 400000);
OLED_Init();
oled_fill(0xff);
OLED_DisplayOn();
一次点亮!效果如下:
尾章,打印字符
点灯的最终目的是打印字符,画图出来。由于精力有限,目前只测试了字符,画图还等后续。
代码占空间,就不发了,将以附件形式上传整个工程。
先看看效果吧:
文章来源于Sipeed点灯鼠,原文链接:https://bbs.sipeed.com/thread/588
搬运请注明原文地址