之前大多使用模拟方式进行I2C器件操作,一直想试试硬件方式,正好GD32E231C8T6片上资源包含了I2C,官方DEMO里也有使用例程,于是就尝试利用手上的一片0.69寸的OLED进行测试。
一、I2C资源简介
从官方资料上看GD32E231C8T6具有两个I2C(I2C0、I2C1),最高速度可达1MHz。
官方提供的用户手册对于I2C章节的描述非常详细,结合固件库参考手册及例程对于I2C的学习、理解有着非常积极的指导作用。如:
OLED非常小巧96x16像素,自制的一个小模块,对外5根连线:SCL、SDA、RST、VCC、GND,利用了板子上“Ardunio”的PB6、PB7、PB8三个端口:
二、程序实现
程序参考了DEMO,OLED驱动也是东拼西凑而来。下面是一些主要代码片段:
void i2c_gpio_config(void)//I2C端口配置
{
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_I2C0);
//rcu_periph_clock_enable(RCU_PMU);
gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_6);//设置PB6为SCL
gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_7);//设置PB7为SDA
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_6);
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,GPIO_PIN_6);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_7);
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,GPIO_PIN_7);
i2c_clock_config(I2C0, I2C0_SPEED, I2C_DTCY_2);//快速模式400KH
i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, OLED069_ADDS);
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
i2c_enable(I2C0);
}
void WriteDat(uint8_t I2C_Data)//写数据
{
//write_i2c(OLED_DEV_ADDR,0x40, I2C_Data);
while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)); //等待I2C总线空闲
i2c_start_on_bus(I2C0); //向I2C总线发送启动条件
while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)); //等待设置SBSEND位
i2c_master_addressing(I2C0, OLED069_ADDS, I2C_TRANSMITTER);//向I2C总线发送OLED地址(0X78)
while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)); //等待设置ADDSEND位
i2c_flag_clear(I2C0,I2C_FLAG_ADDSEND); //清除ADDSEND位
while(SET != i2c_flag_get(I2C0, I2C_FLAG_TBE)); //等待传输数据缓冲区为空
i2c_data_transmit(I2C0, 0x40); //写数据0x40
while(!i2c_flag_get(I2C0, I2C_FLAG_BTC)); //等待设置BTC位
i2c_data_transmit(I2C0, I2C_Data); //oled写入数据
while(!i2c_flag_get(I2C0, I2C_FLAG_BTC)); //等待设置BTC位
i2c_stop_on_bus(I2C0); //向I2C总线发送停止条件
while(I2C_CTL0(I2C0)&0x0200); //等待停止条件完成
}
void WriteCmd(uint8_t I2C_Command)//写命令
{
//write_i2c(OLED_DEV_ADDR,0x00, I2C_Command);
while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)); //等待I2C总线空闲
i2c_start_on_bus(I2C0); //向I2C总线发送启动条件
while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)); //等待设置SBSEND位
i2c_master_addressing(I2C0, OLED069_ADDS, I2C_TRANSMITTER); //向I2C总线发送OLED地址(0X78)
while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)); //等待设置ADDSEND位
i2c_flag_clear(I2C0,I2C_FLAG_ADDSEND); //清除ADDSEND位
while(SET != i2c_flag_get(I2C0, I2C_FLAG_TBE)); //等待传输数据缓冲区为空
i2c_data_transmit(I2C0, 0x00); //写命令0x00
while(!i2c_flag_get(I2C0, I2C_FLAG_BTC)); //等待设置BTC位
i2c_data_transmit(I2C0, I2C_Command); //oled写入数据
while(!i2c_flag_get(I2C0, I2C_FLAG_BTC)); //等待设置BTC位
i2c_stop_on_bus(I2C0); //向I2C总线发送停止条件
while(I2C_CTL0(I2C0)&0x0200); //等待停止条件完成
}
int main(void)
{
systick_config();
i2c_gpio_config();//OLED端口配置
OLED_Init(); //OLED初始化
while(1)
{
OLED_ShowStr(0,0,"GD32E231C8T6",2);
delay_1ms(1000);
OLED_ShowCN(0,0,0); //兆
OLED_ShowCN(16,0,1); //易
OLED_ShowCN(32,0,2); //创
OLED_ShowCN(48,0,3); //新
OLED_ShowCN(64,0,4); //科
OLED_ShowCN(80,0,5); //技
delay_1ms(1000);
}
}
三、结果
下面是将上次RTC实验的程序加入后重新写了一个12x16的字体,这样可以将整个像素点都利用上显得更加饱满,想着做块手表戴戴。
|
|