913|7

5697

帖子

8

TA的资源

版主

 

【CW32L052测评】硬件I2C驱动OLED屏 [复制链接]

 

一直以来,大家对硬件I2C的驱动与使用有点不大支持,因为I2C硬件驱动,相比模拟的时序掌握比较难入手,移植也不是很方便,所以I2C模拟时序大行其道。

经过几天的学习CW32L052的用户手册,我发现其硬件的I2C的驱动的掌握难点在于,对其过 I2C 状态寄存器 I2Cx_STAT的掌握是一个难点,在其用户手册中,他的状态达28个之多,其中的26个为正常接收或发送状态,2个特殊状态(0xF8:I2C总线无可用信息;0x00: 总线错误)。其I2C状态码如下表所示:

image.png   image.png

经过学习官方的cw32l052_i2c.c中的函数,结合我以住驱动SSD1306的经验,成细的驱动了OLED屏,现在驱动方法分享如下:

1、选取合适的硬件I2C驱动管脚, 由于我原来在L083开发板上面使用了与LCD段码屏的管脚导致不起时序,所以这次我避免用到有可能起冲突的管脚。经查看原理图,开发板上的PB8,PB9是接到的开发板的EEPROM上的,原理图如下:

image.png  于是,我选取PB8为SCL,PB9为SDA,经查看用户手册,这两个管脚为I2C1,复用管脚代码如下:

  PB08_AFx_I2C1SCL();
  PB09_AFx_I2C1SDA();

初始化的次序为:使能GPIOB的时钟——使能I2C1时钟——复用GPIO为I2C1——配置GPIO为GPIO_MODE_OUTPUT_OD模式——配置I2C的波特率——配置I2C1总线——使用能I2C1,具体代码如下:

void OLED_I2C_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure = {0};
	I2C_InitTypeDef I2C_InitStruct = {0};
	
//	__RCC_GPIOB_CLK_ENABLE();
//	__RCC_I2C1_CLK_ENABLE();
	CW_SYSCTRL->AHBEN_f.GPIOB  = 1;
	CW_SYSCTRL->APBEN1_f.I2C1 = 1U;    //
	
	PB08_AFx_I2C1SCL();
  PB09_AFx_I2C1SDA();
	GPIO_InitStructure.Pins = I2C1_SCL_GPIO_PIN | I2C1_SDA_GPIO_PIN;
	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
	GPIO_Init(I2C1_SCL_GPIO_PORT, &GPIO_InitStructure);
	
	I2C_InitStruct.I2C_Baud = 0x1; // 48000 000/(8*(1+11) = 500k
	I2C_InitStruct.I2C_BaudEn = ENABLE;
  I2C_InitStruct.I2C_FLT = DISABLE;
  I2C_InitStruct.I2C_AA =  DISABLE;
	
	I2C1_DeInit();
  I2C_Master_Init(CW_I2C1,&I2C_InitStruct);//初始化模块

	I2C_Cmd(CW_OLED_I2C, ENABLE);
}

此次I2C不起用中断,采取循环获取I2C状态来决定下一步数据写入的方法。

需要驱动OLED,首先发出起始信号,然后判断STA状态寄存器的状态来做下一步的动作。而驱动SSD1306最基本的函数为向其写入一个byte的数据,其他的都是可以通用的,具体实现的代码如下:

//向OLED寄存器地址写一个byte的数据
int I2C_WriteByte(uint8_t addr,uint8_t data)
{
	uint8_t u8i = 0, u8State;
  uint16_t timeout = 0xffff;
	I2C_GenerateSTART(CW_OLED_I2C, ENABLE);
	//获取状态
	while(1)
	{
		
		while((0 == I2C_GetIrq(CW_OLED_I2C)) && timeout--);
		if(timeout == 0) return 1;
		u8State = I2C_GetState(CW_OLED_I2C);
		switch(u8State) 
		{
			case 0x08:  //发送完START信号
				I2C_GenerateSTART(CW_OLED_I2C, DISABLE);
				I2C_Send7bitAddress(CW_OLED_I2C, OLED_ADDR, 0x00);
				break;
			case 0x18:  //发送完SLA+W信号,ACK已收到
				I2C_SendData(CW_OLED_I2C, addr);
				break;
			case 0x28:
				I2C_SendData(CW_OLED_I2C, data);
				u8i ++;
				break;
			case 0x20: //发送完SLA+W后从机返回NACK
				break;
			case 0x38: //主机在发送 SLA+W 阶段或者发送数据阶段丢失仲载  或者  主机在发送 SLA+R 阶段或者回应 NACK 阶段丢失仲裁
				I2C_GenerateSTART(CW_OLED_I2C, ENABLE);
        break;
			case 0x30:
				I2C_GenerateSTOP(CW_OLED_I2C, ENABLE);
				break;
			default:
				break;		
		}
		if(u8i>1)
		{
			I2C_GenerateSTOP(CW_OLED_I2C, ENABLE);
			I2C_ClearIrq(CW_OLED_I2C);
			break;
		}
		I2C_ClearIrq(CW_OLED_I2C);
		
	}
	return 0;
}

实现好这个函数后,我们使用以住的驱动库,就可以顺利的点亮OLED屏了,在主函数中我们写入测试函数:

	OLED_Init();
	SysTickDelay(500);
	OLED_Fill(0xff);
	SysTickDelay(500);
	OLED_Fill(0x00);
	SysTickDelay(500);
	OLED_ShowStr(31,2,"Hello World",1);
	OLED_ShowStr(10,5,"Hello CW32L052",2);

顺利的点亮OLED屏,效果如下:

62decae25ae3c6b7bc26085716f51a1.jpg  其余的代码我附上工程源码,有不足之处,请大家多多指教:

oled.zip (5.74 KB, 下载次数: 6)

最新回复

谢谢分享,期待后续!   详情 回复 发表于 2023-7-21 15:30
 
 
 

回复
举报

1524

帖子

0

TA的资源

五彩晶圆(初级)

 

初始化的次序总结的不错,谢谢分享

点评

感谢大佬的关注与肯定,我会继续努力学习,并把学习的分享给大家!  详情 回复 发表于 2023-7-21 08:43
 
 
 

回复

5697

帖子

8

TA的资源

版主

 
火辣西米秀 发表于 2023-7-21 08:40 初始化的次序总结的不错,谢谢分享

感谢大佬的关注与肯定,我会继续努力学习,并把学习的分享给大家!

 
 
 

回复

1288

帖子

0

TA的资源

五彩晶圆(初级)

 
不错的资料分享,初始化的次序总结的不错,谢谢分享

点评

谢谢大佬关注与肯定,学习使我快乐,生命不此,学习不断!  详情 回复 发表于 2023-7-21 11:57
 
 
 

回复

5697

帖子

8

TA的资源

版主

 
lkh747566933 发表于 2023-7-21 11:28 不错的资料分享,初始化的次序总结的不错,谢谢分享

谢谢大佬关注与肯定,学习使我快乐,生命不此,学习不断!

 
 
 

回复

5318

帖子

4

TA的资源

版主

 

Hello eeworld!

 
 
 

回复

6754

帖子

2

TA的资源

五彩晶圆(中级)

 

谢谢分享,期待后续!

点评

多谢大佬关注,一定加油继续写好帖子!  详情 回复 发表于 2023-7-21 15:52
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 
 

回复

5697

帖子

8

TA的资源

版主

 
freebsder 发表于 2023-7-21 15:30 谢谢分享,期待后续!

多谢大佬关注,一定加油继续写好帖子!

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

猜你喜欢
随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表