【BLE 5.3无线MCU CH582】5、硬件I2C驱动0.96吋OLED
[复制链接]
系列文章:
【BLE 5.3无线MCU CH582】1、初识CH582开发板(开箱)
【BLE 5.3无线MCU CH582】2、MounRiver IDE初体验
【BLE 5.3无线MCU CH582】3、非阻塞方式点灯
【BLE 5.3无线MCU CH582】4、串口不定长数据接收
1、关于CH582的I2C接口
可以看出只有1个I2C接口。
2、I2C引脚
PB13:SCL,PB12:SDA。
3、开发板上I2C的引脚
需要注意的是I2C与USB2共用引脚,同一时刻只能使用其中一个功能。
4、代码实现
(1)初始化i2c
void I2cInit(void)
{
GPIOB_ModeCfg( GPIO_Pin_12|GPIO_Pin_13, GPIO_ModeIN_PU );
I2C_Init( I2C_Mode_I2C, 400000, I2C_DutyCycle_2, I2C_Ack_Enable, I2C_AckAddr_7bit, 0x35 );
I2C_Cmd(ENABLE);
}
(2)写OLED
下面分写命令和数据.
void OledWriteCmd(UINT8 var)
{
while( I2C_GetFlagStatus( I2C_FLAG_BUSY ) != RESET );
I2C_GenerateSTART( ENABLE );
while( !I2C_CheckEvent( I2C_EVENT_MASTER_MODE_SELECT ) );
I2C_Send7bitAddress( I2C_SLAVE_ADDRESS7, I2C_Direction_Transmitter );
while( !I2C_CheckEvent( I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );
while( I2C_GetFlagStatus( I2C_FLAG_TXE ) != SET );
I2C_SendData( 0x00 );
while( I2C_GetFlagStatus( I2C_FLAG_TXE ) != SET );
I2C_SendData( var );
while( !I2C_CheckEvent( I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
I2C_GenerateSTOP( ENABLE );
}
void OledWriteData(UINT8 var)
{
while( I2C_GetFlagStatus( I2C_FLAG_BUSY ) != RESET );
I2C_GenerateSTART( ENABLE );
while( !I2C_CheckEvent( I2C_EVENT_MASTER_MODE_SELECT ) );
I2C_Send7bitAddress( I2C_SLAVE_ADDRESS7, I2C_Direction_Transmitter );
while( !I2C_CheckEvent( I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );
while( I2C_GetFlagStatus( I2C_FLAG_TXE ) != SET );
I2C_SendData( 0x40 );
while( I2C_GetFlagStatus( I2C_FLAG_TXE ) != SET );
I2C_SendData( var );
while( !I2C_CheckEvent( I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
I2C_GenerateSTOP( ENABLE );
}
(3)OLED相关驱动
//坐标设置:也就是在哪里显示
void OledSetPos(uint8_t x, uint8_t y)
{
//以下3个寄存器只在页寻址的模式下有效
SSD1306_WriteCmd(0xb0+y); //页地址设置 0xb0~0xb7
SSD1306_WriteCmd(((x&0xf0)>>4)|0x10); //列高位地址设置
SSD1306_WriteCmd((x&0x0f)); //列低位地址设置
}
//开启Oled显示
void OledDisplayOn(void)
{
SSD1306_WriteCmd(0X8D); //SET DCDC命令
SSD1306_WriteCmd(0X14); //DCDC ON
SSD1306_WriteCmd(0XAF); //DISPLAY ON
}
//关闭Oled显示
void OledDisplayOff(void)
{
SSD1306_WriteCmd(0X8D); //SET DCDC命令
SSD1306_WriteCmd(0X10); //DCDC OFF
SSD1306_WriteCmd(0XAE); //DISPLAY OFF
}
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样
void OledClear(void)
{
uint8_t 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);
} //更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127,y:0~7
//Char_Size:选择字体 16/12
void OledShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size)
{
uint8_t c=0,i=0;
c=chr-' ';//得到偏移后的值
if(x>MAX_COLUMN-1)
{
x=0;
y=y+2;
}
if(Char_Size ==16)
{
OledSetPos(x,y);
for(i=0;i<8;i++)
{
SSD1306_WriteData(F8X16[c*16+i]);//先写上半部分
}
OledSetPos(x,y+1);
for(i=0;i<8;i++)
{
SSD1306_WriteData(F8X16[c*16+i+8]);//后写下半部分
}
}
else
{
OledSetPos(x,y);
for(i=0;i<6;i++)
{
SSD1306_WriteData(F6x8[c][i]);
}
}
}
//显示一个字符串
void OledShowString(uint8_t x,uint8_t y,char *str,uint8_t Char_Size)
{
unsigned char j=0;
while (str[j]!='\0')
{
OledShowChar(x,y,str[j],Char_Size);
x+=8;
if(x>120)
{
x=0;
y+=2;
}
j++;//移动一次就是一个page,取值0-7
}
}
//显示汉字
//由于汉字是16*16大小的,所以最多显示4行汉字
//index:在汉字取模中的索引
void OledShowCN(uint8_t x,uint8_t y,uint8_t index)
{
uint8_t t;
OledSetPos(x,y);
for(t=0;t<16;t++)
{
SSD1306_WriteData(Hzk[index][t]);
}
OledSetPos(x,y+1);
for(t=0;t<16;t++)
{
SSD1306_WriteData(Hzk[index][t+16]);
}
}
(4)OLED初始化
//SSD1306初始化
void OledInit(void)
{
DelayMs(300);
DelayMs(300);
//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
}
(5)显示测试
void OledDisplayTest(void)
{
I2cInit();
OledInit();
OledClear();
OledShowString(20,0,(char *)("EEWORLD"),16);
OledShowCN(84,0,0);
OledShowCN(100,0,1);
OledShowString(32,3,(char *)("CH582"),16);
OledShowCN(80,3,2);
OledShowCN(96,3,3);
OledShowString(40,6,(char *)("2022-03-15"),16);
}
(6)一些定义
#define I2C_SLAVE_ADDRESS7 0x78 //0x3c,0x3d
#define MAX_COLUMN 128
#define MAX_ROW 64
#define SSD1306_WriteCmd OledWriteCmd
#define SSD1306_WriteData OledWriteData
5、现象
|