08、OLED实验(模拟IIC)

硬件连接:
PA5        SCL
PA7        SDA

GPIO初始化

/*
	@brief			初始化OLED与单片机的IO接口
	@param			无
	@retval			无
 */
static void OLED_GPIO_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;	//定义一个GPIO_InitTypeDef类型的结构体
	
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);	//打开GPIOC的外设时钟
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;	//选择控制的引脚
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;	//设置为通用开漏输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//设置输出速率为50MHz
	GPIO_Init(GPIOA,&GPIO_InitStructure);	//调用库函数初始化GPIOA
	
	OLED_SCLK_Set();	//设PC2(SCL)为高电平
	OLED_SDIN_Set();	//设PC3(SDA)为高电平
}

模拟IIC



/*
	@brief			模拟IIC起始信号
	@param			无
	@retval			无
 */
static void OLED_IIC_Start(void)
{

	OLED_SCLK_Set();	//时钟线置高
	OLED_SDIN_Set();	//信号线置高
	delay(1);	//延迟1us
	OLED_SDIN_Clr();	//信号线置低
	delay(1);	//延迟1us
	OLED_SCLK_Clr();	//时钟线置低
	delay(1);	//延迟1us
}


/*
	@brief			模拟IIC停止信号
	@param			无
	@retval			无
 */
static void OLED_IIC_Stop(void)
{
	OLED_SDIN_Clr();	//信号线置低
	delay(1);	//延迟1us
	OLED_SCLK_Set();	//时钟线置高
	delay(1);	//延迟1us
	OLED_SDIN_Set();	//信号线置高
	delay(1);	//延迟1us
}


/*
	@brief			模拟IIC读取从机应答信号
	@param			无
	@retval			无
 */
static unsigned char IIC_Wait_Ack(void)
{
	unsigned char ack;

	OLED_SCLK_Clr();	//时钟线置低
	delay(1);	//延迟1us
	OLED_SDIN_Set();	//信号线置高
	delay(1);	//延迟1us
	OLED_SCLK_Set();	//时钟线置高
	delay(1);	//延迟1us

	if(OLED_READ_SDIN())	//读取SDA的电平
		ack = IIC_NO_ACK;	//如果为1,则从机没有应答
	else
		ack = IIC_ACK;		//如果为0,则从机应答

	OLED_SCLK_Clr();//时钟线置低
	delay(1);	//延迟1us

	return ack;	//返回读取到的应答信息
}
/*
	@brief			IIC写入一个字节
	@param			IIC_Byte:写入的字节
	@retval			无
 */
static void Write_IIC_Byte(unsigned char IIC_Byte)
{
	unsigned char i;  //定义变量
	for(i=0;i<8;i++) //for循环8次
	{
		OLED_SCLK_Clr();	//时钟线置低,为传输数据做准备
		delay(1);	//延迟1us

		if(IIC_Byte & 0x80)	//读取最高位
		  	OLED_SDIN_Set();//最高位为1
		else
			OLED_SDIN_Clr();	//最高位为0

		IIC_Byte <<= 1;  //数据左移1位
		delay(1);	//延迟1us
		OLED_SCLK_Set(); //时钟线置高,产生上升沿,把数据发送出去
		delay(1);	//延迟1us
	}
	OLED_SCLK_Clr();	//时钟线置低
	delay(1);	//延迟1us

	while(IIC_Wait_Ack());	//从机应答
}

/*
	@brief			IIC写入命令
	@param			IIC_Command:写入的命令
	@retval			无
 */
static void Write_IIC_Command(unsigned char IIC_Command)
{
   OLED_IIC_Start();
   Write_IIC_Byte(0x78);//写入从机地址,SD0 = 0
   Write_IIC_Byte(0x00);//写入命令
   Write_IIC_Byte(IIC_Command);//数据
   OLED_IIC_Stop();  //发送停止信号
}


/*
	@brief			IIC写入数据
	@param			IIC_Data:数据
	@retval			无
 */
static void Write_IIC_Data(unsigned char IIC_Data)
{
   OLED_IIC_Start();
   Write_IIC_Byte(0x78);	//写入从机地址,SD0 = 0
   Write_IIC_Byte(0x40);	//写入数据
   Write_IIC_Byte(IIC_Data);//数据
   OLED_IIC_Stop();		//发送停止信号
}

OLED驱动

/*
	@brief			对OLED写入一个字节
	@param			dat:数据
					cmd:1,写诶数据;0,写入命令
	@retval			无
 */
void OLED_WR_Byte(unsigned char dat,unsigned char cmd)
{
	if(cmd) 
	  {
       Write_IIC_Data(dat); //写入数据
	  }
	else {
       Write_IIC_Command(dat); //写入命令
	}
}


/*
	@brief			设置数据写入的起始行、列
	@param			x: 列的起始低地址与起始高地址;0x00~0x0f:设置起始列低地址(在页寻址模式);
						0x10~0x1f:设置起始列高地址(在页寻址模式)
					y:起始页地址 0~7
	@retval			无
 */
void OLED_Set_Pos(unsigned char x, unsigned char y) 
{ 
	OLED_WR_Byte(0xb0+y,OLED_CMD);//写入页地址
	OLED_WR_Byte((x&0x0f),OLED_CMD);  //写入列的地址  低半字节
	OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);//写入列的地址 高半字节
}   	     	  


/*
	@brief			开显示
	@param			无
	@retval			无
 */ 
void OLED_Display_On(void)
{
	OLED_WR_Byte(0X8D,OLED_CMD);  //设置OLED电荷泵
	OLED_WR_Byte(0X14,OLED_CMD);  //使能,开
	OLED_WR_Byte(0XAF,OLED_CMD);  //开显示
}


/*
	@brief			关显示
	@param			无
	@retval			无
 */  
void OLED_Display_Off(void)
{
	OLED_WR_Byte(0XAE,OLED_CMD);  //关显示
	OLED_WR_Byte(0X8D,OLED_CMD);  //设置OLED电荷泵
	OLED_WR_Byte(0X10,OLED_CMD);  //失能,关
}		   			 


/*
	@brief			清屏
	@param			无
	@retval			无
 */	  
void OLED_Clear(void)  
{  
	unsigned char 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); //写入 0 清屏
	}
}


/*
	@brief			显示一个字符
	@param			x:起始列
					y:起始页,SIZE = 16占两页;SIZE = 12占1页
					chr:字符
	@retval			无
 */
void OLED_ShowChar(unsigned char x,unsigned char y,unsigned char chr)
{      	
	unsigned char c=0,i=0;	
		c=chr-' '; //获取字符的偏移量	
		if(x>Max_Column-1){x=0;y=y+2;} //如果列数超出了范围,就从下2页的第0列开始

		if(SIZE ==16) //字符大小如果为 16 = 8*16
			{
				OLED_Set_Pos(x,y);	//从x y 开始画点
				for(i=0;i<8;i++)  //循环8次 占8列
				OLED_WR_Byte(F8X16[c*16+i],OLED_DATA); //找出字符 c 的数组位置,先在第一页把列画完
				OLED_Set_Pos(x,y+1); //页数加1
				for(i=0;i<8;i++)  //循环8次
				OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA); //把第二页的列数画完
			}
		else 	//字符大小为 6 = 6*8
			{	
				OLED_Set_Pos(x,y+1); //一页就可以画完
				for(i=0;i<6;i++) //循环6次 ,占6列
				OLED_WR_Byte(F6x8[c][i],OLED_DATA); //把字符画完
			}
}
/*
	@brief			显示字符串
	@param			x:起始列
					y:起始页
					*chr:第一个字符首地址
	@retval			无
 */
void OLED_ShowString(unsigned char x,unsigned char y,unsigned char *chr)
{
	unsigned char j=0; //定义变量

	while (chr[j]!='\0') //如果不是最后一个字符
	{		
		OLED_ShowChar(x,y,chr[j]); //显示字符
		x+=8; //列数加8 ,一个字符的列数占8
		if(x>=128){x=0;y+=2;} //如果x大于等于128,切换页,从该页的第一列显示
		j++; //下一个字符
	}
}


/*
	@brief			显示中文
	@param			x:起始列;一个字体占16列
					y:起始页;一个字体占两页
					no:字体的序号
	@retval			无
 */
void OLED_ShowCHinese(unsigned char x,unsigned char y,unsigned char no)
{      			    
	unsigned char t,adder=0; //定义变量

	OLED_Set_Pos(x,y);	//从 x y 开始画点,先画第一页
    for(t=0;t<16;t++) //循环16次,画第一页的16列
		{
			OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);//画no在数组位置的第一页16列的点
			adder+=1; //数组地址加1
     	}	
		OLED_Set_Pos(x,y+1); //画第二页
    for(t=0;t<16;t++)//循环16次,画第二页的16列
		{	
			OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);//画no在数组位置的第二页16列的点
			adder+=1;//数组地址加1
        }					
}

/*
	@brief			OLED初始化函数
	@param			无
	@retval			无
 */				    
void OLED_Init(void)
{
	OLED_GPIO_Init();	//GPIO口初始化
 
	delay_ms(200);	//延迟,由于单片机上电初始化比OLED快,所以必须加上延迟,等待OLED上复位完成

	OLED_WR_Byte(0xAE,OLED_CMD);	//关闭显示

	OLED_WR_Byte(0x00,OLED_CMD);	//设置低列地址
	OLED_WR_Byte(0x10,OLED_CMD);	//设置高列地址
	OLED_WR_Byte(0x40,OLED_CMD);	//设置起始行地址
	OLED_WR_Byte(0xB0,OLED_CMD);	//设置页地址

	OLED_WR_Byte(0x81,OLED_CMD); 	// 对比度设置,可设置亮度
	OLED_WR_Byte(0xFF,OLED_CMD);	//  265  

	OLED_WR_Byte(0xA1,OLED_CMD);	//设置段(SEG)的起始映射地址;column的127地址是SEG0的地址
	OLED_WR_Byte(0xA6,OLED_CMD);	//正常显示;0xa7逆显示

	OLED_WR_Byte(0xA8,OLED_CMD);	//设置驱动路数(16~64)
	OLED_WR_Byte(0x3F,OLED_CMD);	//64duty
	
	OLED_WR_Byte(0xC8,OLED_CMD);	//重映射模式,COM[N-1]~COM0扫描

	OLED_WR_Byte(0xD3,OLED_CMD);	//设置显示偏移
	OLED_WR_Byte(0x00,OLED_CMD);	//无偏移
	
	OLED_WR_Byte(0xD5,OLED_CMD);	//设置震荡器分频
	OLED_WR_Byte(0x80,OLED_CMD);	//使用默认值
	
	OLED_WR_Byte(0xD9,OLED_CMD);	//设置 Pre-Charge Period
	OLED_WR_Byte(0xF1,OLED_CMD);	//使用官方推荐值
	
	OLED_WR_Byte(0xDA,OLED_CMD);	//设置 com pin configuartion
	OLED_WR_Byte(0x12,OLED_CMD);	//使用默认值
	
	OLED_WR_Byte(0xDB,OLED_CMD);	//设置 Vcomh,可调节亮度(默认)
	OLED_WR_Byte(0x40,OLED_CMD);	////使用官方推荐值
	
	OLED_WR_Byte(0x8D,OLED_CMD);	//设置OLED电荷泵
	OLED_WR_Byte(0x14,OLED_CMD);	//开显示
	
	OLED_WR_Byte(0xAF,OLED_CMD);	//开启OLED面板显示
	OLED_Clear();        //清屏
	OLED_Set_Pos(0,0); 	 //设置数据写入的起始行、列
}  

mian

int main(void)
{
	OLED_Init();  //OLED初始化
	OLED_Clear();
	
	OLED_ShowString(0,2," OLED TEST ");// OLED TEST
	
	OLED_ShowCHinese(2*8,0,0);// 技
	OLED_ShowCHinese(4*8,0,1);// 新
	OLED_ShowCHinese(6*8,0,2);// 电
	OLED_ShowCHinese(8*8,0,3);// 子
	OLED_ShowCHinese(10*8,0,4);// 科
	OLED_ShowCHinese(12*8,0,5);// 技
	
    
	while(1)
	{
		
	}
}
发布了274 篇原创文章 · 获赞 97 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/imxlw00/article/details/104720468