AIP650E显示驱动


前言

应用于51单片机


一、API650E显示驱动端口配置

首先对端口进行配置,默认可以选择为强推挽输出模式,其中SDA端口根据API650E芯片使用手册可以得到,需要将其在恰当的时候配置为输入模式。
在这里插入图片描述
在这里插入图片描述
因此需要将SDA在接收8位数据以后,将IO口配置为输入,然后再将SDA手动置“0”,(结合波形分析出,下面会详细阐述这一点)。
配置端口代码如下:

//宏定义SDA端口和SCL端口
P2CON |= 0x20; P2PH |= 0x00; //2.5-SDA-默认为强推挽输出
P2CON |= 0x40; P2PH |= 0x00; //2.6-SCL-默认为强推挽输出	

//SDA端口
#define AIP650E_SDA_OUTPUT           {P2CON |= 0x20; P2PH |= 0x00;}  //2.5配置为输出
#define AIP650E_SDA_INPUT            {P2CON |= 0x00; P2PH |= 0x20;}  //2.5配置为输入

#define IO_SDA_PIN							(P25)
#define IO_SCL_PIN							(P26)

#define OUT_AIP650E_SDA(sig)      { if(sig>0){IO_SDA_PIN = 1;} else {IO_SDA_PIN = 0;} }
#define OUT_AIP650E_SCL(sig)      { if(sig>0){IO_SCL_PIN = 1;} else {IO_SCL_PIN = 0;} }

二、延时函数

以下是本段代码用到的延时,使用Nop语句,注意:在51单片机中写成“nop()”,区别于32单片机。

void f_NOPDelay(uint16_t i_Value)
{
	uint16_t i;
	for (i = 0; i < i_Value; i++)
	{
		_nop_();
	}	
}

static  void  f_AIP650E_Delay(void)
{
	f_NOPDelay(5); /* Nop延时函数 */
}

三、模拟IIC起始、终止信号

从芯片手册中可以看出两个端口都是先高电平,接着是低电平,最后才开始数据的传输。因此在起始信号配置中,如以下代码中所示首先是高电平,然后延时一段时间后变成低电平。
在这里插入图片描述

  1. 起始信号
//功能描述: 根据数据手册得出**起始信号**以下配置 
void f_AIP650E_SendStart(void)
{
	AIP650E_SDA_OUTPUT;
	OUT_AIP650E_SDA(1);  												
	OUT_AIP650E_SCL(1);   												
	f_AIP650E_Delay();
	OUT_AIP650E_SDA(0);
	f_AIP650E_Delay();
	OUT_AIP650E_SCL(0); 	
}
  1. 起始信号
void f_AIP650E_SendStop(void)
{
	AIP650E_SDA_OUTPUT;
	OUT_AIP650E_SDA(0);	
	OUT_AIP650E_SCL(0);
	f_AIP650E_Delay();
	OUT_AIP650E_SCL(1);	
	f_AIP650E_Delay();	
	OUT_AIP650E_SDA(1);
}

四、模拟应答信号

由于本人也是小白,因此在应答信号这里进行了一些分析。
主要的目的是对以下这两行代码的分析

OUT_AIP650E_SDA(0);
OUT_AIP650E_SDA(1);

原因:在芯片手册中可以看到,
本电路的数据传输带有应答信号 ACK,在传输数据的过程中,在时钟线的第九个时钟芯片内部会产生一个应答信号 ACK 将 DIO(SDA) 管脚拉低。无论是命令写入或者是数据写入读出时,在一个 8 位字节后的第 9 位都是 ACK 信号输出。
在这里插入图片描述
在进行数据传送时,在SCL的上升沿锁存数据SCL为高电平期间,SDA线上的数据必须保持稳定,只有在SCL线上的信号为低电平期间,SDA线上的数据状态才允许改变,且SDA线上的数据不能在SCL为下降沿改变

1.屏蔽OUT_AIP650E_SDA()的时序图

因为是第一次使用模拟IIC,对“模拟”理解的不太深入,因此认为接收8为数据以后芯片会发出一个低电平信号给SDA,只需要主控芯片读出该低电平信号就行。(此时已经将SDA端口配置为输入**(对主控芯片来说)**)。因此第一次将直接就将该行代码屏蔽,只是将SDA配置为输入,源码如下:

u8 f_AIP650E_Wait_Ack(void)
{
	u8 ucErrTime=0;
	AIP650E_SDA_INPUT;
//  OUT_AIP650E_SDA(0);
//  OUT_AIP650E_SDA(1);  
	f_AIP650E_Delay();		
	OUT_AIP650E_SCL(1);	
	f_AIP650E_Delay();		
	while(IO_SDA_PIN)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			f_AIP650E_SendStop();
			return 1;  //表示传输出问题了,不能在继续显示了。
		}
	}
	OUT_AIP650E_SCL(0);		
	return 0;	
}
//发送一次数据的代码
void f_AIP650E_Send_Byte(uint8_t i_Data)
{                        
	uint8_t i;   
	AIP650E_SDA_OUTPUT;
	OUT_AIP650E_SCL(0);	
	f_AIP650E_Delay();
	for(i = 0; i < 8; i++)		
	{              
		if((i_Data & 0x80) >> 7)
		{
			OUT_AIP650E_SDA(1);		
		}
		else
		{
			OUT_AIP650E_SDA(0);		
		}
		i_Data <<= 1; 
		f_AIP650E_Delay();		
		OUT_AIP650E_SCL(1);
		f_AIP650E_Delay();
		OUT_AIP650E_SCL(0);
		f_AIP650E_Delay();
	}
}

//整个过程。
extern uint8_t WriteOneByte(uint8_t SlaverAddr,uint8_t DataToWrite)
{
	uint8_t ErrFlag = 0;
	f_AIP650E_SendStart();
	f_AIP650E_Send_Byte(SlaverAddr);
	ErrFlag = f_AIP650E_Wait_Ack();
	if(ErrFlag == 1)
		return ErrFlag;
	f_AIP650E_Send_Byte(DataToWrite);    							   
	ErrFlag = f_AIP650E_Wait_Ack(); 
	if(ErrFlag == 1)
		return ErrFlag;		    	   
  f_AIP650E_SendStop();
	return 0;  
}

//再试用过程中只需要调用该函数即可,其中调用之前,需要进行一次初始化,参考芯片手册,本文选择的是0x4871。
在这里插入图片描述

WriteOneByte(0x48,0x71);
WriteOneByte(0x6E,0x80);

以下是波形分析:
在这里插入图片描述
第一次传输的数据是0x6E,在传输完成以后需要一个ACK信号,本身第一次的数据最低位是“0”,虽然将该端口配置了上拉电阻输入,但是依旧保持低电平,因此被SCL锁存到,完成了一次应答。接着进行0x80数据传输。结合源码可以清晰的分析出这段时序图,本文就不在详细赘述。分析的整体思路就是:

  1. 首先需要明白数据的地方就是图中标记的,黄色代表SCK(时钟线),绿色代表的是数据线。

  2. 为什么数据可以有效传递,这是因为芯片手册中明确说明了“SCK(时钟线)由低到高的过程才能有效的传递数据”,
    在这里插入图片描述

  3. 结合程序以及上述图片内容一步一步认真的走程序,就可以完整的分析上述的时序图,分析完以后代表了你彻底理解了针对AIP650E显示芯片模拟IIC传输过程。

2.OUT_AIP650E_SDA(1)的时序图

以下是源码:

u8 f_AIP650E_Wait_Ack(void)
{
	u8 ucErrTime=0;
	AIP650E_SDA_INPUT;
    OUT_AIP650E_SDA(1);  
	f_AIP650E_Delay();		
	OUT_AIP650E_SCL(1);	
	f_AIP650E_Delay();		
	while(IO_SDA_PIN)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			f_AIP650E_SendStop();
			return 1;  
		}
	}
	OUT_AIP650E_SCL(0);		
	return 0;	
}

以下是时序图:
在这里插入图片描述
可以看出在传输0x80时,无法有效传递,也就是说在应答信号时,将

   OUT_AIP650E_SDA(1); 

并没有收到该端口自动变低电平的信号,因此传输不成功,而中间这一段这么长的空闲,就是这段代码导致的

	while(IO_SDA_PIN)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			f_AIP650E_SendStop();
			return 1;  
		}
	}

因为此时IO_SDA_PIN = 1;由于没有收到低电平信号,因此一直在执行While()里面的程序,直到最后达到最大时间,执行停止信号函数。

f_AIP650E_SendStop();

在这里插入图片描述
标红框的这一段是主循环的时间,跟我调用该函数位置有关。

3.OUT_AIP650E_SDA(0)的时序图

u8 f_AIP650E_Wait_Ack(void)
{
	u8 ucErrTime=0;
	AIP650E_SDA_INPUT;
	OUT_AIP650E_SDA(0);
	f_AIP650E_Delay();		
	OUT_AIP650E_SCL(1);	
	f_AIP650E_Delay();		
	while(IO_SDA_PIN)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			f_AIP650E_SendStop();
			return 1; 
		}
	}
	OUT_AIP650E_SCL(0);		
	return 0;	
}

在这里插入图片描述
可以看出与第一次的时序图完全一样,

总结

个人认为,在传输8为数据以后,在配置完SDA端口作为输入端口以后,需要手动的将SDA的端口电平置为“0”。避免由于上一个8为数据的最低位是1,硬件又不能将SDA端口自动置“0”,从而出现显示错误现象。(本次的第一个8位数据是0x6E,也就是0110 1110)因此可以看出最地位是0,不会影响下一次的8位数据传递,但是假如第二个8,也就是段选的时候数据为(0x81)那么传输的时候就会出现错误,因为SDA将会一直保持高电平,并不能满足ACK应答信号。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Liu_08290727/article/details/144895344

转载链接

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

慈悲不渡自绝人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值