资讯详情

GD32F310G8 -【6】硬件I2C&软件I2C驱动0.96OLED

GD32F310-硬件I2C&软件I2C驱动OLED


I2C 简介及特点

  • 并行总线至 I2C 转换和接口总线协议;
  • 同一接口可实现主机功能和从机功能;
  • 主从机之间的双向数据传输;
  • 支持 7 位和 10 地址模式和广播寻址;
  • 支持 I2C 多主机模式;
  • 支持标速(最高) 100 kHz),快速(最高 400 kHz) 和快速 模式(最高 1MHz);
  • 可以在从机模式下配置 SCL 主动拉低;
  • 支持 DMA 模式;
  • 兼容 SMBus 2.0 和 PMBus;
  • 两个中断:字节成功发送中断和错误事件中断;
  • 可选择的 PEC (报文错误校验) 生成和校验;

I2C (内部集成电路总线) 模块提供符合工业标准的两线串行接口,可用于 MCU 和外部 I2C 设备通信。 I2C 总线使用两条串行线:串行数据线 SDA 串行时钟线 SCL。 I2C 实现了接口模块 I2C 协议的速度模式、快速模式和快速模式 模式,具备 CRC 计算和验证工作 能、支持 SMBus(系统管理总线) 和 PMBus 此外,还支持多主机 I2C 总线 架构。 I2C 也支持接口模块 DMA 模式,可有效减轻 CPU 的负担。

开发环境&参考文档

  • Keil-MDK 5.34
  • Windows10
  • 固件库-GD32F3x0_Firmware_Library_V2.2.0
  • GD32F310xx-数据手册-Rev1.1
  • GD32F3x0-用户手册-Rev2.5
  • GD32F3x0-固件库使用指南-Rev1.2

代码部分

I2C 初始化配置

I2C.h 文件

#ifndef _IIC_H_ #define _IIC_H_  #include "gd32f3x0.h"  void HW_I2cInit(void);  #endif  

I2C.c 文件

#include "iic.h"   void HW_I2cInit(void) { 
          rcu_periph_clock_enable(RCU_GPIOB);///启用外设时钟功能  rcu_periph_clock_enable(RCU_I2C0);    gpio_af_set(GPIOB,GPIO_AF_1,GPIO_PIN_6);///端口复用串口模式  gpio_af_set(GPIOB,GPIO_AF_1,GPIO_PIN_7);    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_6);//设置GPIO模式  gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);//设置GPIO输出类型和速度    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_7); gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7); i2c_deinit(I2C0);//复位I2C0 i2c_clock_config(I2C0, 100000, I2C_DTCY_2);//设置波特率 i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x78);//设置模式、传输数据长度、主机地址 i2c_enable (I2C0);//使能外设 i2c_ack_config(I2C0,I2C_ACK_ENABLE); } 

OLED 初始化函数

oled.h 文件

#ifndef __OLED_H
#define __OLED_H 

#include "iic.h"
#include "stdlib.h"

#define OLED_MODE 0
#define SIZE 8
#define XLevelL 0x00
#define XLevelH 0x10
#define Max_Column 128
#define Max_Row 32
#define Brightness 0xFF 
#define X_WIDTH 128
#define Y_WIDTH 32 
//-----------------OLED 软件I2C端口定义---------------- 
#define OLED_SCLK_Clr() gpio_bit_reset(GPIOA, GPIO_PIN_2)//设置Pin脚为高电平//SCL IIC接口的时钟信号
#define OLED_SCLK_Set() gpio_bit_set(GPIOA, GPIO_PIN_2)

#define OLED_SDIN_Clr() gpio_bit_reset(GPIOA, GPIO_PIN_3)//SCL IIC接口的数据信号
#define OLED_SDIN_Set() gpio_bit_set(GPIOA, GPIO_PIN_3)
 		     
#define OLED_CMD 0 //写命令
#define OLED_DATA 1 //写数据

#define S_I2C 0//软件IIC或硬件IIC开关

#define u8 unsigned char
#define u32 unsigned int

//OLED控制用函数
void fill_picture(unsigned char fill_Data);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Wait_Ack(void);
void Write_IIC_Command(unsigned char IIC_Command);
void Write_IIC_Data(unsigned char IIC_Data);
void Write_IIC_Byte(unsigned char IIC_Byte);

void OLED_WR_Byte(unsigned dat,unsigned cmd);  
void OLED_Display_On(void);
void OLED_Display_Off(void);	   							   		    
void OLED_Init(void);
void OLED_Clear(void);
void OLED_DrawPoint(u8 x,u8 y,u8 t);
void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot);
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size);
void OLED_ShowString(u8 x,u8 y, u8 *p,u8 Char_Size);	 
void OLED_Set_Pos(unsigned char x, unsigned char y);
void OLED_ShowCHinese(u8 x,u8 y,u8 no);
void OLED_DrawBMP(unsigned char x0, 
				unsigned char y0,
				unsigned char x1, 
				unsigned char y1,
				unsigned char BMP[]);



#endif 
	 




oled.c 文件

软件I2C与硬件I2C的选定在 .h 文件中有说明。#define S_I2C 0//软件IIC或硬件IIC开关

具体区别在下列两个函数中 Write_IIC_Command() Write_IIC_Data()

#include "oled.h"
#include "stdlib.h"
#include "oledfont.h" 
#include "iic.h"
//OLED 的显存
//[0]0 1 2 3 ... 127 
//[1]0 1 2 3 ... 127 
//[2]0 1 2 3 ... 127 
//[3]0 1 2 3 ... 127 
//[4]0 1 2 3 ... 127 
//[5]0 1 2 3 ... 127 
//[6]0 1 2 3 ... 127 
//[7]0 1 2 3 ... 127 

/********************************************** //Software IIC Start **********************************************/
void IIC_Start(void)
{ 
        
	OLED_SCLK_Set();
	OLED_SDIN_Set();
	OLED_SDIN_Clr();
	OLED_SCLK_Clr();
}
/********************************************** //Software IIC Stop **********************************************/
void IIC_Stop(void)
{ 
        
	OLED_SCLK_Set();
	OLED_SDIN_Clr();
	OLED_SDIN_Set();
}
/********************************************** //Software IIC Ack **********************************************/
void IIC_Wait_Ack(void)
{ 
        
	OLED_SCLK_Set() ;
	OLED_SCLK_Clr();
}
/********************************************** // 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;
		m=m&0x80;
		if(m==0x80)
		{ 
        
			OLED_SDIN_Set();
		}
		else 
		OLED_SDIN_Clr();
		da=da<<1;
		OLED_SCLK_Set();
		OLED_SCLK_Clr();
	}
}
/********************************************** // IIC Write Command **********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{ 
        
	#if S_I2C
	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();
	#else
	while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
	i2c_start_on_bus (I2C0);
	while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));//进入主机模式
	i2c_master_addressing(I2C0, 0x78, I2C_TRANSMITTER);
	while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));//判断地址发送出去
	i2c_flag_clear (I2C0, I2C_FLAG_ADDSEND);//清除ADDSEND位
	while(SET != i2c_flag_get(I2C0, I2C_FLAG_TBE));//进入数据发送状态
	i2c_data_transmit (I2C0, 0x00);
	while(!i2c_flag_get(I2C0, I2C_FLAG_BTC));
	i2c_data_transmit (I2C0, IIC_Command);
	while(!i2c_flag_get(I2C0, I2C_FLAG_BTC));
	i2c_stop_on_bus (I2C0);
	while(I2C_CTL0(I2C0)&0x0200);
	#endif
}
/********************************************** // IIC Write Data **********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{ 
        
	#if S_I2C
	IIC_Start();
	Write_IIC_Byte(0x78);			//Slave address,SA0=0
	IIC_Wait_Ack();	
	Write_IIC_Byte(0x40);			//write data
	IIC_Wait_Ack();	
	Write_IIC_Byte(IIC_Data);
	IIC_Wait_Ack();	
	IIC_Stop();
	#else
	while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
	i2c_start_on_bus (I2C0);
	while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));//进入主机模式
	i2c_master_addressing(I2C0, 0x78, I2C_TRANSMITTER);
	while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));//判断地址发送出去
	i2c_flag_clear (I2C0, I2C_FLAG_ADDSEND);//清除ADDSEND位
	while(SET != i2c_flag_get(I2C0, I2C_FLAG_TBE));//进入数据发送状态
	i2c_data_transmit (I2C0, 0x40);
	while(!i2c_flag_get(I2C0, I2C_FLAG_BTC));
	i2c_data_transmit (I2C0, IIC_Data);
	while(!i2c_flag_get(I2C0, I2C_FLAG_BTC));
	i2c_stop_on_bus (I2C0);
	while(I2C_CTL0(I2C0)&0x0200);
	#endif
}
void OLED_WR_Byte(unsigned dat,unsigned cmd)
{ 
        
	if(cmd)
	{ 
        
		Write_IIC_Data(dat);
	}
	else 
	{ 
        
		Write_IIC_Command(dat);	
	}
}
/******************************************** //Fill Picture ********************************************/
void fill_picture(unsigned char fill_Data)
{ 
        
	unsigned char m,n;
	for(m=0;m<8;m++)
	{ 
        
		OLED_WR_Byte(0xb0+m,0);		//page0-page1
		OLED_WR_Byte(0x00,0);		//low column start address
		OLED_WR_Byte(0x10,0);		//high column start address
		for(n=0;n<128;n++)
		{ 
        
			OLED_WR_Byte(fill_Data,1);
		}
	}
}
/********************************************** //Set Position //坐标设置 **********************************************/
void OLED_Set_Pos(unsigned char x, unsigned char y) 
{ 
         	
	OLED_WR_Byte(0xb0+y,OLED_CMD);
	OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
	OLED_WR_Byte((x&0x0f),OLED_CMD); 
}   	  
/********************************************** //Turn on OLED display //开启OLED显示 **********************************************/
void OLED_Display_On(void)
{ 
        
	OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
	OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON
	OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
}   
/********************************************** //Turn off OLED display //关闭OLED显示 **********************************************/
void OLED_Display_Off(void)
{ 
        
	OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
	OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
	OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
}	
/********************************************** //清屏函数,清完屏,整个屏幕是黑色的! **********************************************/	   			 
void OLED_Clear(void)  
{ 
          
	u8 i,n;		    
	for(i=0;i<8;i++)  
	{ 
          
		OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
		OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
		OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址 
		for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); 
	} //更新显示
}
/********************************************** //亮屏函数,整个屏幕点亮! **********************************************/	 
void OLED_On(void)  
{ 
          
	u8 i,n;		    
	for(i=0;i<8;i++)  
	{ 
          
		OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
		OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
		OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址 
		for(n=0;n<128;n++)OLED_WR_Byte(1,OLED_DATA); 
	} //更新显示
}
/********************************************** //在指定位置显示一个字符,包括部分字符 //x:0~127 //y:0~63 //mode:0,反白显示;1,正常显示 //chr:要显示的字符 //size:选择字体 16/12 **********************************************/	  
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
{ 
              	
	unsigned char c=0,i=0;	
	c=chr-' ';//得到偏移后的值,为什么做偏移可查看 ASCII 表 
	if(x>Max_Column-1){ 
        x=0;y=y+2;}
	if(Char_Size ==16)
		{ 
        
			OLED_Set_Pos(x,y);	
			for(i=0;i<8;i++)
			OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
			OLED_Set_Pos(x,y+1);
			for(i=0;i<8;i++)
			OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
		}
		else 
		{ 
        	
			OLED_Set_Pos(x,y);
			for(i=0;i<6;i++)
			OLED_WR_Byte(F6x8[c][i],OLED_DATA);	
		}
}
/********************************************** //m^n函数 **********************************************/	  
u32 oled_pow(u8 m,u8 n)
{ 
        
	u32 result=1;	 
	while(n--)result*=m;    
	return result;
}	
/********************************************** //显示2个数字 //x:0~127 //y:0~63 //num:数值(0~4294967295); //len :数字的位数 //size:字体大小 **********************************************/	  			  	 		  
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2)
{ 
                 	
	u8 t,temp;
	u8 enshow=0;						   
	for(t=0;t<len;t++)
	{ 
        
		temp=(num/
        标签: 集成电路2sa1013g547g2p81u集成电路

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台