蓟县集团网站建设,山东省住房城乡建设厅门户网站,模仿网站制作,网站网店建设一、什么是I2C#xff1f; I2C总线#xff0c;全称Inter-Integrated Circuit#xff08;互连集成电路#xff09;#xff0c;是一种由Philips#xff08;现NXP半导体#xff09;公司在1980年代初开发的同步 串行 半双工通信总线。 二、有了串口通信为什么要使用I2C…一、什么是I2C I2C总线全称Inter-Integrated Circuit互连集成电路是一种由Philips现NXP半导体公司在1980年代初开发的同步 串行 半双工通信总线。 二、有了串口通信为什么要使用I2C
串口通信对比I2C有一些缺点 1. 串口通信通常需要至少三条线TX、RX和GND而 I2C 总线仅需要两条信号线SDA和SCL 2. 串口通信仅支持一对一通信而 I2C 总线支持多机通信允许单个主机与多个从机设备进行通信 3. 串口通信通常无应答机制而 I2C 必须有应答机制 4. 串口通讯一般是异步通信而 I2C 使用同步传输方式数据在时钟信号SCL的控制下传输。
三、I2C的工作原理以及特点 四、IIC总线时序
4.1 起始信号 代码书写方式如下 //开始信号 void oled_i2c_start(void) { OLED_SCL_SET(); OLED_SDA_SET(); OLED_SDA_RESET(); OLED_SCL_RESET(); } 4.2 停止信号 //停止信号 void oled_i2c_stop(void) { OLED_SCL_SET(); OLED_SDA_RESET(); OLED_SDA_SET(); } 4.3 应答信号 //应答信号 void oled_i2c_ack(void) { OLED_SCL_SET(); OLED_SCL_RESET(); } 4.4 读写时序 一般都是发送很少接收这里只展现发送数据 //写一个字节信号 void oled_i2c_write_byte(uint8_t data) { uint8_t i,tmp; tmp data; for(i0;i8;i) { if((tmp 0x80) 0x80)//取出最高位判断最高位是不是1 OLED_SDA_SET();//如果最高位是1则sda给一个高电平 else OLED_SDA_RESET();//如果最高位是0则sda给一个低电平 tmp tmp 1; OLED_SCL_SET(); OLED_SCL_RESET(); } } //写一个字节信号 void oled_i2c_write_byte(uint8_t data) { uint8_t i,tmp; tmp data; for(i0;i8;i) { if((tmp 0x80) 0x80)//取出最高位判断最高位是不是1 OLED_SDA_SET();//如果最高位是1则sda给一个高电平 else OLED_SDA_RESET();//如果最高位是0则sda给一个低电平 tmp tmp 1; OLED_SCL_SET(); OLED_SCL_RESET(); } } 4.5 一次完整的I2C时序 五、OLED实验目的
驱动 OLED 屏幕显示点、线、字符、字符串、汉字、图片等内容。 六、项目实现-OLED通讯协议
复制项目文件19-串口打印功能
重命名为47-OLED实验 打开项目文件
加载文件
代码书写顺序 oled.c
#include oled.h//初始化oled的gpio
void oled_gpio_init(void)
{GPIO_InitTypeDef gpio_initstruct;OLED_I2C_SCL_CLK();OLED_I2C_SDA_CLK();gpio_initstruct.Mode GPIO_MODE_OUTPUT_PP;gpio_initstruct.Pin OLED_I2C_SCL_PIN;gpio_initstruct.Pull GPIO_PULLUP;gpio_initstruct.Speed GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(OLED_I2C_SCL_PORT,gpio_initstruct);gpio_initstruct.Pin OLED_I2C_SDA_PIN;HAL_GPIO_Init(OLED_I2C_SDA_PORT,gpio_initstruct);
}/*IIC协议的分装*/
//开始信号
void oled_i2c_start(void)
{OLED_SCL_SET();OLED_SDA_SET();OLED_SDA_RESET();OLED_SCL_RESET();
}
//停止信号
void oled_i2c_stop(void)
{OLED_SCL_SET();OLED_SDA_RESET();OLED_SDA_SET();
}
//应答信号
void oled_i2c_ack(void)
{OLED_SCL_SET();OLED_SCL_RESET();
}
//写一个字节信号
void oled_i2c_write_byte(uint8_t data)
{uint8_t i,tmp;tmp data;for(i0;i8;i){if((tmp 0x80) 0x80)//取出最高位判断最高位是不是1OLED_SDA_SET();//如果最高位是1则sda给一个高电平elseOLED_SDA_RESET();//如果最高位是0则sda给一个低电平tmp tmp 1;OLED_SCL_SET();OLED_SCL_RESET();}
}
//发送一个命令信号
void oled_write_cmd(uint8_t cmd)
{oled_i2c_start();oled_i2c_write_byte(0x78);oled_i2c_ack();oled_i2c_write_byte(0x00);oled_i2c_ack();oled_i2c_write_byte(cmd);oled_i2c_ack();oled_i2c_stop();
}
//发送一个数据信号
void oled_write_data(uint8_t data)
{oled_i2c_start();oled_i2c_write_byte(0x78);oled_i2c_ack();oled_i2c_write_byte(0x40);oled_i2c_ack();oled_i2c_write_byte(data);oled_i2c_ack();oled_i2c_stop();
}//初始化OLED函数
void oled_init(void)
{oled_gpio_init();
}oled.h
#ifndef __OLED_H__
#define __OLED_H__#include sys.h
/*SCL引脚*/
#define OLED_I2C_SCL_CLK() __HAL_RCC_GPIOB_CLK_ENABLE()
#define OLED_I2C_SCL_PORT GPIOB
#define OLED_I2C_SCL_PIN GPIO_PIN_6
/*SDA引脚*/
#define OLED_I2C_SDA_CLK() __HAL_RCC_GPIOB_CLK_ENABLE()
#define OLED_I2C_SDA_PORT GPIOB
#define OLED_I2C_SDA_PIN GPIO_PIN_7
/*SCL引脚拉高拉低*/
#define OLED_SCL_SET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT,OLED_I2C_SCL_PIN,GPIO_PIN_SET)
#define OLED_SCL_RESET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT,OLED_I2C_SCL_PIN,GPIO_PIN_RESET)
/*SDA引脚拉高拉低*/
#define OLED_SDA_SET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT,OLED_I2C_SDA_PIN,GPIO_PIN_SET)
#define OLED_SDA_RESET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT,OLED_I2C_SDA_PIN,GPIO_PIN_RESET)#endif七、项目实现-OLED实现点、线、字符
mian.c
#include sys.h
#include delay.h
#include led.h
#include uart1.h
#include oled.hextern const unsigned char shuai_data[];int main(void)
{HAL_Init(); /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */led_init();//初始化led灯uart1_init(115200);oled_init();printf(hello world!\r\n);oled_fill(0);//清屏函数//字母A-page0oled_set_cursor(0, 0);oled_write_data(0x00); oled_write_data(0x00);oled_write_data(0xC0);oled_write_data(0x38);oled_write_data(0xE0);oled_write_data(0x00);oled_write_data(0x00);oled_write_data(0x00);//page1oled_set_cursor(0, 1);oled_write_data(0x20);oled_write_data(0x3C);oled_write_data(0x23);oled_write_data(0x02);oled_write_data(0x02);oled_write_data(0x27);oled_write_data(0x38);oled_write_data(0x20);while(1){ }
}oled.c
#include oled.h
#include delay.h//初始化oled的gpio
void oled_gpio_init(void)
{GPIO_InitTypeDef gpio_initstruct;OLED_I2C_SCL_CLK();OLED_I2C_SDA_CLK();gpio_initstruct.Mode GPIO_MODE_OUTPUT_PP;gpio_initstruct.Pin OLED_I2C_SCL_PIN;gpio_initstruct.Pull GPIO_PULLUP;gpio_initstruct.Speed GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(OLED_I2C_SCL_PORT,gpio_initstruct);gpio_initstruct.Pin OLED_I2C_SDA_PIN;HAL_GPIO_Init(OLED_I2C_SDA_PORT,gpio_initstruct);
}/*IIC协议的分装*/
//开始信号
void oled_i2c_start(void)
{OLED_SCL_SET();OLED_SDA_SET();OLED_SDA_RESET();OLED_SCL_RESET();
}
//结束信号
void oled_i2c_stop(void)
{OLED_SCL_SET();OLED_SDA_RESET();OLED_SDA_SET();}
//应答信号
void oled_i2c_ack(void)
{OLED_SCL_SET();OLED_SCL_RESET();
}
//写一个字节信号
void oled_i2c_write_byte(uint8_t data)
{uint8_t i,tmp;tmp data;for(i0;i8;i){if((tmp 0x80) 0x80)//取出最高位判断最高位是不是1OLED_SDA_SET();//如果最高位是1则sda给一个高电平elseOLED_SDA_RESET();//如果最高位是0则sda给一个低电平tmp tmp 1;OLED_SCL_SET();OLED_SCL_RESET();}
}
//发送一个命令信号
void oled_write_cmd(uint8_t cmd)
{oled_i2c_start();oled_i2c_write_byte(0x78);oled_i2c_ack();oled_i2c_write_byte(0x00);oled_i2c_ack();oled_i2c_write_byte(cmd);oled_i2c_ack();oled_i2c_stop();
}
//发送一个数据信号
void oled_write_data(uint8_t data)
{oled_i2c_start();oled_i2c_write_byte(0x78);oled_i2c_ack();oled_i2c_write_byte(0x40);oled_i2c_ack();oled_i2c_write_byte(data);oled_i2c_ack();oled_i2c_stop();
}//初始化OLED函数
void oled_init(void)
{oled_gpio_init();delay_ms(100);oled_write_cmd(0xAE); //设置显示开启/关闭0xAE关闭0xAF开启oled_write_cmd(0xD5); //设置显示时钟分频比/振荡器频率oled_write_cmd(0x80); //0x00~0xFFoled_write_cmd(0xA8); //设置多路复用率oled_write_cmd(0x3F); //0x0E~0x3Foled_write_cmd(0xD3); //设置显示偏移oled_write_cmd(0x00); //0x00~0x7Foled_write_cmd(0x40); //设置显示开始行0x40~0x7Foled_write_cmd(0xA1); //设置左右方向0xA1正常0xA0左右反置oled_write_cmd(0xC8); //设置上下方向0xC8正常0xC0上下反置oled_write_cmd(0xDA); //设置COM引脚硬件配置oled_write_cmd(0x12);oled_write_cmd(0x81); //设置对比度oled_write_cmd(0xCF); //0x00~0xFFoled_write_cmd(0xD9); //设置预充电周期oled_write_cmd(0xF1);oled_write_cmd(0xDB); //设置VCOMH取消选择级别oled_write_cmd(0x30);oled_write_cmd(0xA4); //设置整个显示打开/关闭oled_write_cmd(0xA6); //设置正常/反色显示0xA6正常0xA7反色oled_write_cmd(0x8D); //设置充电泵oled_write_cmd(0x14);oled_write_cmd(0xAF); //开启显示
}
//分装的坐标函数
void oled_set_cursor(uint8_t x, uint8_t y)//x是列y是page
{oled_write_cmd(0xB0 y);oled_write_cmd((x 0x0F) | 0x00); oled_write_cmd(((x 0xF0) 4) | 0x10);
}
//清屏函数
void oled_fill(uint8_t data)
{uint8_t i, j;//外层循环循环pagefor(i 0; i 8; i){oled_set_cursor(0, i);for(j 0; j 128; j)oled_write_data(data);}
}oled.h
#ifndef __OLED_H__
#define __OLED_H__#include sys.h
/*SCL引脚*/
#define OLED_I2C_SCL_CLK() __HAL_RCC_GPIOB_CLK_ENABLE()
#define OLED_I2C_SCL_PORT GPIOB
#define OLED_I2C_SCL_PIN GPIO_PIN_6
/*SDA引脚*/
#define OLED_I2C_SDA_CLK() __HAL_RCC_GPIOB_CLK_ENABLE()
#define OLED_I2C_SDA_PORT GPIOB
#define OLED_I2C_SDA_PIN GPIO_PIN_7
/*SCL引脚拉高拉低*/
#define OLED_SCL_SET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT,OLED_I2C_SCL_PIN,GPIO_PIN_SET)
#define OLED_SCL_RESET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT,OLED_I2C_SCL_PIN,GPIO_PIN_RESET)
/*SDA引脚拉高拉低*/
#define OLED_SDA_SET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT,OLED_I2C_SDA_PIN,GPIO_PIN_SET)
#define OLED_SDA_RESET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT,OLED_I2C_SDA_PIN,GPIO_PIN_RESET)void oled_init(void);
void oled_write_cmd(uint8_t cmd);
void oled_write_data(uint8_t data);
void oled_set_cursor(uint8_t x, uint8_t y);
void oled_fill(uint8_t data);
#endif项目实现-显示任意字符汉字图片 mian.c
#include sys.h
#include delay.h
#include led.h
#include uart1.h
#include oled.hextern const unsigned char shuai_data[];int main(void)
{HAL_Init(); /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */led_init();//初始化led灯uart1_init(115200);oled_init();printf(hello world!\r\n);oled_fill(0);//清屏函数
// //字母A page0
// oled_set_cursor(0, 0);
// oled_write_data(0x00);
// oled_write_data(0x00);
// oled_write_data(0xC0);
// oled_write_data(0x38);
// oled_write_data(0xE0);
// oled_write_data(0x00);
// oled_write_data(0x00);
// oled_write_data(0x00);
// //page1
// oled_set_cursor(0, 1);
// oled_write_data(0x20);
// oled_write_data(0x3C);
// oled_write_data(0x23);
// oled_write_data(0x02);
// oled_write_data(0x02);
// oled_write_data(0x27);
// oled_write_data(0x38);
// oled_write_data(0x20);oled_show_char(0, 0, L, 16);oled_show_char(8, 0, X, 16);oled_show_char(16, 0, ?, 16);oled_show_char(24, 0, 6, 16);// oled_show_string(0, 2, hello LX, 24);// uint8_t i;
// for(i 0; i 5; i)
// oled_show_chinese(i*24, 0, i, 24);// oled_show_image(0, 0, 128, 8, (unsigned char *)shuai_data);while(1){ }
}
oled.c
#include oled.h
#include delay.h
#include font.h//初始化oled的gpio
void oled_gpio_init(void)
{GPIO_InitTypeDef gpio_initstruct;OLED_I2C_SCL_CLK();OLED_I2C_SDA_CLK();gpio_initstruct.Mode GPIO_MODE_OUTPUT_PP;gpio_initstruct.Pin OLED_I2C_SCL_PIN;gpio_initstruct.Pull GPIO_PULLUP;gpio_initstruct.Speed GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(OLED_I2C_SCL_PORT,gpio_initstruct);gpio_initstruct.Pin OLED_I2C_SDA_PIN;HAL_GPIO_Init(OLED_I2C_SDA_PORT,gpio_initstruct);
}/*IIC协议的分装*/
//开始信号
void oled_i2c_start(void)
{OLED_SCL_SET();OLED_SDA_SET();OLED_SDA_RESET();OLED_SCL_RESET();
}
//结束信号
void oled_i2c_stop(void)
{OLED_SCL_SET();OLED_SDA_RESET();OLED_SDA_SET();}
//应答信号
void oled_i2c_ack(void)
{OLED_SCL_SET();OLED_SCL_RESET();
}
//写一个字节信号
void oled_i2c_write_byte(uint8_t data)
{uint8_t i,tmp;tmp data;for(i0;i8;i){if((tmp 0x80) 0x80)//取出最高位判断最高位是不是1OLED_SDA_SET();//如果最高位是1则sda给一个高电平elseOLED_SDA_RESET();//如果最高位是0则sda给一个低电平tmp tmp 1;OLED_SCL_SET();OLED_SCL_RESET();}
}
//发送一个命令信号
void oled_write_cmd(uint8_t cmd)
{oled_i2c_start();oled_i2c_write_byte(0x78);oled_i2c_ack();oled_i2c_write_byte(0x00);oled_i2c_ack();oled_i2c_write_byte(cmd);oled_i2c_ack();oled_i2c_stop();
}
//发送一个数据信号
void oled_write_data(uint8_t data)
{oled_i2c_start();oled_i2c_write_byte(0x78);oled_i2c_ack();oled_i2c_write_byte(0x40);oled_i2c_ack();oled_i2c_write_byte(data);oled_i2c_ack();oled_i2c_stop();
}//初始化OLED函数
void oled_init(void)
{oled_gpio_init();delay_ms(100);oled_write_cmd(0xAE); //设置显示开启/关闭0xAE关闭0xAF开启oled_write_cmd(0xD5); //设置显示时钟分频比/振荡器频率oled_write_cmd(0x80); //0x00~0xFFoled_write_cmd(0xA8); //设置多路复用率oled_write_cmd(0x3F); //0x0E~0x3Foled_write_cmd(0xD3); //设置显示偏移oled_write_cmd(0x00); //0x00~0x7Foled_write_cmd(0x40); //设置显示开始行0x40~0x7Foled_write_cmd(0xA1); //设置左右方向0xA1正常0xA0左右反置oled_write_cmd(0xC8); //设置上下方向0xC8正常0xC0上下反置oled_write_cmd(0xDA); //设置COM引脚硬件配置oled_write_cmd(0x12);oled_write_cmd(0x81); //设置对比度oled_write_cmd(0xCF); //0x00~0xFFoled_write_cmd(0xD9); //设置预充电周期oled_write_cmd(0xF1);oled_write_cmd(0xDB); //设置VCOMH取消选择级别oled_write_cmd(0x30);oled_write_cmd(0xA4); //设置整个显示打开/关闭oled_write_cmd(0xA6); //设置正常/反色显示0xA6正常0xA7反色oled_write_cmd(0x8D); //设置充电泵oled_write_cmd(0x14);oled_write_cmd(0xAF); //开启显示
}
//分装的坐标函数
void oled_set_cursor(uint8_t x, uint8_t y)//x是列y是page
{oled_write_cmd(0xB0 y);oled_write_cmd((x 0x0F) | 0x00); oled_write_cmd(((x 0xF0) 4) | 0x10);
}
//清屏函数
void oled_fill(uint8_t data)
{uint8_t i, j;//外层循环循环pagefor(i 0; i 8; i){oled_set_cursor(0, i);for(j 0; j 128; j)oled_write_data(data);}
}
//指定显示字符 - 列坐标-page -哪个字符-字符大小
void oled_show_char(uint8_t x, uint8_t y, uint8_t num, uint8_t size)
{uint8_t i, j, page;num num - ;page size / 8;if(size % 8)//判断字符大小page;for(j 0; j page; j)//page循环{oled_set_cursor(x, y j);for(i size / 2 * j; i size /2 * (j 1); i){if(size 12)oled_write_data(ascii_6X12[num][i]);else if(size 16)oled_write_data(ascii_8X16[num][i]);else if(size 24)oled_write_data(ascii_12X24[num][i]);}}
}
//显示字符串
void oled_show_string(uint8_t x, uint8_t y, char *p, uint8_t size)
{while(*p ! \0){oled_show_char(x, y, *p, size);x size/2;//偏移字符p;}
}
//显示汉字
void oled_show_chinese(uint8_t x, uint8_t y, uint8_t N, uint8_t size)
{uint16_t i, j;for(j 0; j size/8; j){oled_set_cursor(x, y j);for(i size *j; i size * (j 1); i){if(size 16)oled_write_data(chinese_16x16[N][i]);else if(size 24)oled_write_data(chinese_24x24[N][i]);}}
}
//显示图片
void oled_show_image(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t *bmp)
{uint8_t i, j;for(j 0; j height; j){oled_set_cursor(x, y j);for(i 0; i width; i)oled_write_data(bmp[width * j i]);}
}
oled.h
#ifndef __OLED_H__
#define __OLED_H__#include sys.h
/*SCL引脚*/
#define OLED_I2C_SCL_CLK() __HAL_RCC_GPIOB_CLK_ENABLE()
#define OLED_I2C_SCL_PORT GPIOB
#define OLED_I2C_SCL_PIN GPIO_PIN_6
/*SDA引脚*/
#define OLED_I2C_SDA_CLK() __HAL_RCC_GPIOB_CLK_ENABLE()
#define OLED_I2C_SDA_PORT GPIOB
#define OLED_I2C_SDA_PIN GPIO_PIN_7
/*SCL引脚拉高拉低*/
#define OLED_SCL_SET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT,OLED_I2C_SCL_PIN,GPIO_PIN_SET)
#define OLED_SCL_RESET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT,OLED_I2C_SCL_PIN,GPIO_PIN_RESET)
/*SDA引脚拉高拉低*/
#define OLED_SDA_SET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT,OLED_I2C_SDA_PIN,GPIO_PIN_SET)
#define OLED_SDA_RESET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT,OLED_I2C_SDA_PIN,GPIO_PIN_RESET)void oled_init(void);
void oled_write_cmd(uint8_t cmd);
void oled_write_data(uint8_t data);
void oled_set_cursor(uint8_t x, uint8_t y);
void oled_fill(uint8_t data);
void oled_show_char(uint8_t x, uint8_t y, uint8_t num, uint8_t size);
void oled_show_string(uint8_t x, uint8_t y, char *p, uint8_t size);
void oled_show_chinese(uint8_t x, uint8_t y, uint8_t N, uint8_t size);
void oled_show_image(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t *bmp);
#endiffont.h
#ifndef __FONT_H__
#define __FONT_H__//16号汉字
const unsigned char chinese_16x16[][32]
{ /*汉字的字模*/};//24号汉字
const unsigned char chinese_24x24[][72]
{/*汉字的字模*/
};const unsigned char ascii_6X12[][12]{/*可见的ASCII字符集字模*/
};//16*16 ASCII字符集点阵
const unsigned char ascii_8X16[][16]
{/*可见的ASCII字符集字模*/
};//16*16 ASCII字符集点阵
const unsigned char ascii_12X24[][36]
{/*可见的ASCII字符集字模*/
};
//汉字帅
const unsigned char shuai_data[] {/*汉字帅的字模*/
};#endif