本帖最后由 lisingch 于 2020-6-13 15:43 编辑
对于I2C通信平时使用软件方式比较多,因为其使用比较灵活、移植方便。本次实验使用AC7811QBGE微控制器片上的硬件I2C资源驱动一块0.69寸96*16分辨率的OLED。工程依然使用了“AutoGen Studio”创建。下面是实验过程:
一、实验资源
1、AC7811-MINI开发板;
2、AutoGen Studio 1.2.0;
3、KEIL 5.28.0.0;
4、0.69寸OLED(自制模块)
二、资源简介
AC7811QBGE微控制器片上有两个I2C模块,支持主、从模式, 支持I2C标准模式和快速模式,支持DMA,具有可编程输入毛刺过滤器、传输比特率等。
对于I2C的各种操作模式参考手册中结合寄存器给出了非常细致的描述,通过对手册的学习对I2C协议的学习具有积极的指导作用。在本次实验中只是对OLED设备写数据,AC7811QBGE的I2C模块只充当了主机发送器。如下:
I2C通信中还有一个速率的重要参数需要考虑,实验中具体的配置在下一节中描述。如下图:
三、代码实现
上节图中的公式:fSCL=fbclk/(((SAMPLE_CNT_DIV+1)*(STEP_CNT_DIV+1))*2),其中的主要参数均可在“AutoGen Studio”进行相应配置,
Fbclk=48MHz;SAMPLE_CNT_DIV=14;STEP_CNT_DIV=14,根据配置参数可以计算fSCL=48MHz/((14+1)*(14+1)*2)=106.6KHz,当然也可以根据需要配置更高的通信速率,比如400KHz。
由“AutoGen Studio”生成的I2C初始化代码如下:
/* I2C1 init function */
void ATC_I2C1_Init(void)
{
I2C_ConfigType config;
MSP_I2C_Init(I2C1);
config.sampleCNT = 14;
config.stepCNT = 14;
config.sclAdj = 0;
config.setting.i2cEn = 1;
config.setting.intEn = 0;
config.setting.master = 1;
config.setting.wakeUpEn = 0;
config.setting.swRst = 0;
config.setting.gcaEn = 0;
config.setting.addressExt = 0;
config.setting.syncEn = 1;
config.setting.arbEn = 0;
config.setting.strEn = 0;
config.setting.mntEn = 0;
config.setting.mntIE = 0;
config.setting.dmaRxEn = 0;
config.setting.dmaTxEn = 0;
config.setting.SSIE = 0;
config.setting.rxOFIntEn = 0;
config.setting.txUFIntEn = 0;
config.setting.nackIntEn = 0;
config.addr1 = 127;
I2C_Initialize(I2C1, &config);
}
实验中使用的这个OLED模块当时制作时引出了"RES"复位脚,其实直接将其接高电平也可以工作,实验中还是使用这个引脚:
/**
* @函数名: OLED_RES_Init
* @功 能: 对OLED069的RES引脚初始化
* @参 数: 无
* @返回值: 无
*/
static void OLED_RES_Init(void)
{
OLED069_RES_HIGH();
mdelay(100);
OLED069_RES_LOW();
mdelay(100);
OLED069_RES_HIGH();
}
对于这个OLED器件的操作无非就是向器件地址上写命令各数据,I2C主机“写”函数套用了DEMO:
#define OLED069_ADDS 0X78 //OLED069器件地址
#define OLED069_WRITE_CMD 0X00 //写命令
#define OLED069_WRITE_DAT 0X40 //写数据
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] WriteDat,向OLED写入数据
* @param I2C_Data:数据
* @retval 无
*/
void WriteDat(uint8_t I2C_Data)//写数据
{
uint32_t errorStatus = 0;
I2C_Start(I2C1);
errorStatus = I2C_WriteOneByte(I2C1, OLED069_ADDS);
if (errorStatus == I2C_ERROR_NULL)
{
I2C_WriteOneByte(I2C1, OLED069_WRITE_DAT);
}
if (errorStatus == I2C_ERROR_NULL)
{
I2C_WriteOneByte(I2C1, I2C_Data);
}
I2C_Stop(I2C1);
}
void WriteCmd(uint8_t I2C_Command)//写命令
{
uint32_t errorStatus = 0;
I2C_Start(I2C1);
errorStatus = I2C_WriteOneByte(I2C1, OLED069_ADDS);
if(errorStatus == I2C_ERROR_NULL)
{
errorStatus = I2C_WriteOneByte(I2C1, OLED069_WRITE_CMD);
}
if(errorStatus == I2C_ERROR_NULL)
{
errorStatus = I2C_WriteOneByte(I2C1, I2C_Command);
}
I2C_Stop(I2C1);
}
OLED的分辨率为96*16,主函数中直接向OLED分三屏送显8*16的ASCII数据:
OLED_ShowStr(12, 0, "AutoChips", 2);
mdelay(1000);
OLED_CLS();//清屏
OLED_ShowStr(8, 0, "AC7811QBGE", 2);
mdelay(1000);
OLED_CLS();
OLED_ShowStr(0, 0, "I2C OLED OK!", 2);
mdelay(1000);
OLED_CLS();
四、实验结果
五、实验总结
通过本次实验对AC781X系列微控制器的片上I2C资源的主机发送器模式有了一些认识,对于其他各种工作模式还要进一步学习。
|