【雅特力AT32A403A 车规MCU开发板】+I2C通讯及OLED显示
[复制链接]
本帖最后由 dmzdmz666666 于 2024-1-27 16:40 编辑
第四篇:I2C通讯及OLED显示
这篇文章将来测评AT32A403A的硬件I2C和用I2C驱动OLED。
我选用的OLED是市面上常见的0.96寸OLED,它支持I2C和SPI接口,常见的驱动方式是使用软件I2C或者SPI,这里我将用AT32的硬件I2C将其驱动。
首先,因为市面上用0.96寸的OLED的人很多,所以一些开发者或商家就编写其的通用驱动,为了提高开发效率,避免重复造轮子,我选用某园的驱动,它提供了非常多的例程,我就在其基础上修改。
首先,在hardware文件夹中新建I2C.c、0_96_OLED.c等C文件及其对应的h头文件。
第二步,通过WorkBench配置AT32A403A的硬件I2C,选择I2C1,GPIO默认选择PB6和PB7,具体参数我这里默认。这里要注意,PB6和PB7同时可以与板载SPI Flash相连,但默认是没有相连的,通过JP8进行切换。
新建的I2C.C文件源于官方提供的I2C应用层库函数,位置在AT32A403A_Firmware_Library_V2.0.1\middlewares\i2c_application_library里面,包含对I2C的GPIO的选择和复用功能初始化、使能I2C的时钟、配置I2C的分频系数、传输速率、发送数据、接收数据等。
将WorkBench生成的I2C1初始化代码移植入I2C_Init()函数中。
然后记得使能对应外设的时钟
第三步,将某园的OLED的I2C驱动复制到0_96_OLED.c,面对不同的MCU,只需要移植驱动层,包括OLED指令发送函数和OLED数据发送函数,应用层脱离于具体硬件,不需要移植。
OLED指令发送函数Write_IIC_Command()和OLED数据发送函数Write_IIC_Data()类似,首先发送第一个8位数据:7位从机地址+读写位,因为都是向OLED发送的,所以读写位为0;第二个8位数据为控制字节,如果接下来发送为指令,那么为0x00,如果是数据,那么为0x40;第三个8位数据就是具体的指令或者数据。具体如下。这里需要注意,我重新定义了一个静态I2C结构体,将上述OLED的写入数据和写入命令指定为I2C1,如果不加,当单片机只使能某一个I2C是没啥影响的,但如果使能好几个的话,就容易冲突,因为I2C结构体指定某一I2C通道的程序就在I2C_Init()函数,比如I2C1和I2C2通过hi2cx.i2cx = I2C1和I2C_Init(&hi2cx);/hi2cx.i2cx = I2C2和I2C_Init(&hi2cx);进行初始化,但具体到通讯时就不知道是用哪个通道了,结构体是全局变量,全局影响的。所以最好重新指定一个I2C结构体明确用I2C的哪个通道(当然了 有待验证)。
这里我多说一点,要注意从机的地址,从机地址为0x78,实际是这个0x78是包含了最后一位的读写位0,实际的地址应该是0x78>>1(虽然地址就是写入操作),而之前使用过的小华半导体的HC32F448使用I2C_Master_Transmit()填入的从机地址需要真实的地址0x3C(0x78>>1),因为其会调用I2C_TransAddr()来发送地址,I2C_TransData()来发送数据,而I2C_TransAddr()内部是通过I2C_WriteData(I2Cx, (uint8_t)(u16Addr << 1U) | u8Dir);发送地址,可以看到其会自动将从机地址右移一位并加上读写位,经过它处理才是0x78,所以你填入的从机地址一定要是左移一位的从机地址,当时还踩了几天的坑,呜呜呜呜!!!
而AT32A403A的库函数你填入的从机地址它不会左移或者右移,如果当前是发送模式,就强制将地址的最后一位置0,也就是写入模式,这符合逻辑,最后传入i2c_x->dt的就是0x78,而i2c_x->dt就是I2C的数据寄存器。
移植好这几个核心函数后,其他基本就没什么问题了。然后在主函数调用相关函数就可以啦。
最后写入对应的API,就能显示对应的效果了。
|