概述
本章配置GD32F303使用IIC进行驱动SSD1306的12864OLED。 查阅手册可以得知,PB10、PB11为I2C的接口。 需要GD样片的可以加群申请:615061293 。
视频教学
https://www.bilibili.com/video/BV1od4y1u7t7/
csdn课程
课程更加详细。 https://download.csdn.net/course/detail/37144
样品申请
https://www.wjx.top/vm/wFGhGPF.aspx#
参考文档
GD官方文档GD32F30x_Firmware_Library_V2.1.4下面IIC的Master_transmitter&slave_receiver
时钟使能
/*!
brief enable the peripheral clock
param[in] none
param[out] none
retval none
*/void rcu_config(void){ /* enable GPIOB clock */
rcu_periph_clock_enable(RCU_GPIOB); /* enable I2C1 clock */
rcu_periph_clock_enable(RCU_I2C1);
}
初始化IO
/*!
brief cofigure the GPIO ports
param[in] none
param[out] none
retval none
*/void gpio_config(void){ /* connect PB10 to I2C1_SCL */
/* connect PB11 to I2C1_SDA */
gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_10 | GPIO_PIN_11);
}
IIC初始化
/*!
brief cofigure the I2C0 and I2C1 interfaces
param[in] none
param[out] none
retval none
*/void i2c_config(void)
{ i2c_clock_config(I2C1, 100000, I2C_DTCY_2); /* I2C address configure */
i2c_mode_addr_config(I2C1, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x78); /* enable I2C1 */
i2c_enable(I2C1); /* enable acknowledge */
i2c_ack_config(I2C1, I2C_ACK_ENABLE);
}
配置IIC接口
/*!
brief cofigure the I2C1 interfaces
param[in] none
param[out] none
retval none
*/void i2c_config(void)
{ /* configure I2C1 clock */
i2c_clock_config(I2C1, 100000, I2C_DTCY_2); /* configure I2C1 address */
i2c_mode_addr_config(I2C1, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x78); /* enable I2C1 */
i2c_enable(I2C1); /* enable acknowledge */
i2c_ack_config(I2C1, I2C_ACK_ENABLE);
}
修改IIC发送代码
将Master_transmitter&slave_receiver的IIC发送代码进行修改
/**
* @brief I2C1写函数
* @param addr设备地址
* @param pdata 数据指针
* @param data_length 数据长度
*/
void i2c_write(uint8_t addr, uint8_t *pdata, uint32_t data_length)
{
uint32_t i;
/* wait until I2C bus is idle */
while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY));//等待总线空闲
/* send a start condition to I2C bus */
i2c_start_on_bus(I2C1);//发送start信号
/* wait until SBSEND bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND)); //起始位是否发送
/* send slave address to I2C bus */
i2c_master_addressing(I2C1, addr, I2C_TRANSMITTER);//设置从机地址和执行发送操作
/* wait until ADDSEND bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_ADDSEND));//主机模式下地址是否发送
/* clear ADDSEND bit */
i2c_flag_clear(I2C1, I2C_FLAG_ADDSEND);//清除标志位主机模式下地址是否发送
/* wait until the transmit data buffer is empty */
while(!i2c_flag_get(I2C1, I2C_FLAG_TBE));//发送期间I2C_DATA为空
for(i = 0; i < data_length; i++){
/* data transmission */
i2c_data_transmit(I2C1, pdata[i]);//发送数据
/* wait until the TBE bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_TBE));//发送期间I2C_DATA为空
}
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C1);//在I2C总线上生成停止位
/* wait until stop condition generate */
while(I2C_CTL0(I2C1)&0x0200); //等待直到停止条件生成
}
OLED
查看文档可以知道地址为b0111100或者b0111101,当R/W位置写0的时候,才能进行写的操作,那么地址默认为0x78(b01111000)或者0x7A(b01111010)
参考程序
这里使用0.96OLED显示屏_STM32F103C8_IIC_V1.0来进行移植查看工程可以知道主要是有3个文件来进行OLED的驱动,移入OLE.h .c 、oledfont.h 、 bmp.h 移入文件之后要注意导入C文件。
记得添加路径。删除没有用的头文件 删除sys.h文件
删除delay.h文件
可以查看stdint.h
在oled.h中添加u8 u32定义 也可以直接修改
typedef unsigned char u8;typedef unsigned int u32;
先把oled.h添加主程序中。
查看oled.h,可以看到IIC定义,同时也是模拟IIC,可以注释掉
查看oled.c,可以看到是模拟iic,这些都可以注释不要,我们使用的是iIC,不是模拟。
将IIC写放入oled.c中。 记得导入#include 'gd32f30x_i2c.h'头文件
记得在oled.h中申明 要使用uint8和uint32,导入头文件#include 'stdint.h'
IIC写一个字节可以修改为如下所示。
/**********************************************
// IIC Write byte
**********************************************/
void Write_IIC_Byte(unsigned char IIC_Byte)
{
// unsigned char i;
// unsigned char m,da;
// da=IIC_Byte;
// OLED_SCLK_Clr();
// for(i=0;i< 8;i++)
// {
// m=da;
// // OLED_SCLK_Clr();
// m=m&0x80;
// if(m==0x80)
// {OLED_SDIN_Set();}
// else OLED_SDIN_Clr();
// da=da< < 1;
// OLED_SCLK_Set();
// OLED_SCLK_Clr();
// }
uint8_t byte[1] = {};
byte[0]=IIC_Byte;
i2c_write(0x78,byte, 1);
}
IIC写指令 向0x78设备写命令0x00的IIC_Command指令。
/**********************************************
// IIC Write Command
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{
// IIC_Start();
// Write_IIC_Byte(0x78); //Slave address,SA0=0
// IIC_Wait_Ack();
// Write_IIC_Byte(0x00); //write command
// IIC_Wait_Ack();
// Write_IIC_Byte(IIC_Command);
// IIC_Wait_Ack();
// IIC_Stop();
uint8_t byte[2] = {};
byte[0] =0x00;
byte[1] =IIC_Command;
i2c_write(0x78,byte, 2);
}
IIC写数据 向0x78设备写数据0x40的IIC_Data指令。
/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{
// IIC_Start();
// Write_IIC_Byte(0x78); //D/C#=0; R/W#=0
// IIC_Wait_Ack();
// Write_IIC_Byte(0x40); //write data
// IIC_Wait_Ack();
// Write_IIC_Byte(IIC_Data);
// IIC_Wait_Ack();
// IIC_Stop();
uint8_t byte[2] = {};
byte[0] =0x40;
byte[1] =IIC_Data;
i2c_write(0x78,byte, 2);
}
在oled.c中,OLED_Init初始化可以注释掉gpio初始化
在oled.c中,OLED_Init初始化中有个延时800ms。 导入 #include 'systick.h' 可以使用delay_1ms(800);
取模
在oledfont.h中放入字库
char Hzk[][32]={
// 记(0) 帖(1) 年(2) 月(3) 日(4)
{0x40,0x40,0x42,0xCC,0x00,0x00,0x00,0x84,0x84,0x84,0x84,0x84,0xFC,0x00,0x00,0x00},
{0x00,0x00,0x00,0x7F,0x20,0x10,0x00,0x3F,0x40,0x40,0x40,0x40,0x41,0x40,0x70,0x00},/*'记',0*/
/* (16 X 16 , 宋体 )*/
{0x00,0xF8,0x08,0xFF,0x08,0xF8,0x00,0x00,0x00,0x00,0xFF,0x10,0x10,0x10,0x10,0x00},
{0x00,0x0F,0x00,0xFF,0x08,0x0F,0x00,0xFF,0x41,0x41,0x41,0x41,0x41,0xFF,0x00,0x00},/*'帖',1*/
/* (16 X 16 , 宋体 )*/
{0x00,0x20,0x18,0xC7,0x44,0x44,0x44,0x44,0xFC,0x44,0x44,0x44,0x44,0x04,0x00,0x00},
{0x04,0x04,0x04,0x07,0x04,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x04,0x04,0x00},/*'年',2*/
/* (16 X 16 , 宋体 )*/
{0x00,0x00,0x00,0xFE,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0xFE,0x00,0x00,0x00},
{0x80,0x40,0x30,0x0F,0x02,0x02,0x02,0x02,0x02,0x02,0x42,0x82,0x7F,0x00,0x00,0x00},/*'月',3*/
/* (16 X 16 , 宋体 )*/
{0x00,0x00,0x00,0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0xFF,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xFF,0x00,0x00,0x00,0x00},/*'日',4*/
/* (16 X 16 , 宋体 )*/
};
在main.c中添加显示
OLED_Init(); //初始化OLED
OLED_Clear() ;
OLED_ShowCHinese(0,0,0);//记
OLED_ShowCHinese(16,0,1);//帖
OLED_ShowNum(0,2,2022,4,16);//显示ASCII字符的码值
OLED_ShowCHinese(32,2,2);//年
OLED_ShowNum(48,2,9,1,16);//显示ASCII字符的码值
OLED_ShowCHinese(64,2,3);//月
OLED_ShowNum(80,2,10,2,16);//显示ASCII字符的码值
OLED_ShowCHinese(96,2,4);//日
字体大小只有2个
显示字符
OLED_ShowString(40,2,'ZXY',8);
图片
图片放在bmp.h中。
#ifndef __BMP_H
#define __BMP_H
unsigned char BMP1[]={
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x1F,0x1F,0x7F,0xFF,0xFF,
0xFF,0xFF,0xFF,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x0F,0x0F,
0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,
0x8F,0x8F,0x8F,0x8F,0x8F,0x8F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC7,0xC7,0xC7,0xC4,0x04,0x04,0x04,0x07,0xFF,
上一篇:GD32F303固件库开发(15)----外部中断EXTI
下一篇:RT-Thread开发GD32F450添加spiflash外设的步骤
设计资源 培训 开发板 精华推荐
- OrangeBox 汽车连接域控制器开发平台
- 使用 Diodes Incorporated 的 ZLDO330 的参考设计
- RD-409,将 FL7733A LED 驱动器用于 LED 驱动器应用的参考设计
- LT3970EDDB-3.3 5V 同步降压转换器的典型应用
- LT1307BCMS8 升压/降压转换器的典型应用电路
- LT8335EDDB 3V 至 6V 输入、24V 升压转换器的典型应用电路
- 使用 NXP Semiconductors 的 TDA1521Q 的参考设计
- TLE4309 可调线性低压降 LED 驱动器的典型应用
- DC227A-C,用于 LT1247CS8 和 LT1431CS8 的演示板,35W,隔离式正向转换器,半砖,36 至 72Vin,5V 或 3.3Vout at 7A,500V DC 隔离,高效率
- 立创EDA电路测试板(贴片类)