#申请原创# #有奖活动#[url=home.php?mod=space&uid=760190]@21小跑堂 [/url]
【前言】
i2c为MCU常见的外设,可以用模拟或者硬件i2c来实现通信,i2c可以实现主从通信,可以实现一对多,或者多对一个的主从通信,只需要两根数据线就可以实现,在IO紧张的情况下可以实现少的IO来实现多个外设的通信。AC7840x拥有1个I2C0,最大通信时钟频率为400K。可以通过引脚复用,可以使用信号多路复用灵活实现引脚的分配。同时AC7804x的I2C还可以实现低功耗模式。而OLED屏也是最常见的外设,可以实现低能耗的显示解决方案。此实验验证i2c的写出数据的方法。
【配置】
官方的示例中给出主机模式的两种方案,主机中断发送与DMA发送。
在初始化时,先声明结构体,然后对PA2、PA3进行信号复用,复用为PORT_MUX_ALT3。
然后对配置结构体的7bit地址模式 ,声明从机地址,使用中断方式,同步禁能,仲裁禁能,波特率设置为400K,无回调函数,进行配置,代码如下:
<p>void II2CGpioInit(void)</p><p>{</p><p>/* I2C 配置结构体 */</p><p> i2c_master_user_config_t i2c_master_config;</p><p> /* 清I2C 配置结构体 */</p><p> memset(&i2c_master_config, 0, sizeof(i2c_master_user_config_t));</p><p> memset(&g_i2c_master_state, 0, sizeof(i2c_master_state_t));</p><p> /* PA2->SDA,PA3->SCL */</p><p> GPIO_DRV_SetMuxModeSel(PORTA, (gpio_channel_type_t)2U, PORT_MUX_ALT3);</p><p> GPIO_DRV_SetMuxModeSel(PORTA, (gpio_channel_type_t)3U, PORT_MUX_ALT3);</p><p> i2c_master_config.is10bitAddr = false; /* 7bit地址模式 */</p><p> i2c_master_config.slaveAddress = OLED_ADDRESS; /* i2c 从机地址 */</p><p> i2c_master_config.transferType = I2C_USING_INTERRUPTS; /* i2c 使用中断方式 */</p><p> i2c_master_config.syncEn = false; /* i2c 同步禁能 */</p><p> i2c_master_config.arbitration = true; /* i2c 仲裁禁能 */</p><p> i2c_master_config.baudRate = 400000; /* i2c 波特率设置 */</p><p> i2c_master_config.callback = NULL; /* 无回调函数 */</p><p> I2C_DRV_MasterInit(I2C0_INSTANCE,&i2c_master_config,&g_i2c_master_state); /* i2c 调用底层函数后生效 */</p><p>}</p>
3、组装i2c发送指令与数据的两个函数,ssd1306发送指令与数据的不同就是数据第一位不同,分别为指令为0x00,数据为0x40。组装函数如下,我们使用I2C_DRV_MasterSendDataBlocking进行数据传输。
<p>void Write_IIC_Command(uint8_t IIC_Command) {</p><p>uint8_t buff[2] = {0};</p><p>buff[0] = 0x00;</p><p>buff[1] = IIC_Command;</p><p>I2C_DRV_MasterSendDataBlocking(I2C0_INSTANCE, buff, 2, ENABLE, 100);</p><p>}</p><p>void Write_IIC_Data(uint8_t IIC_Data) {</p><p>uint8_t buff[2] = {0};</p><p>buff[0] = 0x40;</p><p>buff[1] = IIC_Data;</p><p>I2C_DRV_MasterSendDataBlocking(I2C0_INSTANCE, buff, 2, ENABLE, 100);</p><p>}</p>
4、由于AC7840x拥有大的内存,所以组装了一个发送整行128个数据的发送函数。由于在前面发个一个数据位的指令,所以要声明一个129的buffer,然后一次发送一个整行的数据,代码如下:
<p>uint8_t oled_transmit(uint8_t* pdata, uint16_t size)</p><p>{</p><p> /* initialization parameters */</p><p>uint8_t buffer[129] = {0};</p><p>uint8_t i;</p><p> /* 发送本次发送为数据的命令 */</p><p>buffer[0] = 0x40;</p><p> for(i=1; i<size+1; i++)</p><p>{</p><p>buffer[i] = *pdata;</p><p>pdata ++;</p><p>}</p><p>I2C_DRV_MasterSendDataBlocking(I2C0_INSTANCE, buffer, size+1, \</p><p> ENABLE, 100);</p><p>return 1;</p><p>}</p>
到此oled的移植代码就结束了,其余代码我附在工程源码,需要的自取。
主函数我这里添加测试函数
<p>int main(void)</p><p>{</p><p> SystemClock_Config(); /* 系统时钟配置 */</p><p> InitDebug();</p><p> printf("I2C0 Master Test\n");</p><p> SystemCoreClockUpdate(); /* 更新系统时钟频率 */</p><p> OLED_Init();</p><p> GUI_ShowString(10,0,"hello Wrold",16,1);</p><p> GUI_ShowString(10,16,"AC7840x",16,0);</p><p>OLED_Display();</p><p> while(1)</p><p> {</p><p> }</p><p>}</p>
【实验效果】
【总结】
AC7840x拥用1路I2C外设,并且固件库封装了常用的i2c发送函数,用户只需要几步就可以实现i2c的数据通信,并实现OLED屏的驱动。
01_I2C_Master_oled.zip
(112.6 KB)
|