本文引用地址:
1 前言
OLED是非常常用的显示设备,可以由4线、3线的spi驱动,也可以使用2线的IIC来驱动。百问网提供了spi_OLED的驱动例程,这次使用IIC来驱动,并且使用基于面向对象的编程来实现。
2 实现步聚
1.配置IIC,打开RASC后,在栈中增加rau_master_I2C,并设置channel为0b20即通道2,选择SCL为P112与SDA为P110。
【注】我原来设置了为通道0或者通道1,但是都与UART或的外接晶振的IO有冲突,所以只能选择这个通道但是他还是与tx、LED有冲突,如果自己的设计的话还需要考虑到IO的冲突问题。
2.生成代码后,我拷贝drv_oled.h/c 以及driv_spi.h到工程之中。
view plaincopy to clipboardprint?
1.
3.在原来的OLED工程之中,是使用spi来驱动的,同时原来的RA5他的内存与频率相比RA0要高很多,需要进行很多的更改。首先添加回调函数,回调函数中判断接收状态,并更新:
view plaincopy to clipboardprint?
1. void sau_i2c_master_callback(i2c_master_callback_
args_t * p_args)
2. {
3. switch (p_args- event)
4. {
5. c ase I2C_MASTER_EVENT_TX_COMPLETE:
6. {
7. gI2C1TxCplt = true;
8. break;
9. }
10. c aseI2C_MASTER_EVENT_RX_COMPLETE:
11. {
12. gI2C1RxCplt = true;
13. break;
14. }
15. default:
16. {
17. gI2C1TxCplt = gI2C1RxCplt = false;
18. break;
19. }
20. }
21. }
4.接着修改发送等待超时函数,在我们向i2c 总线发送数据结事后,我们需要用这个函数来判断是否发送结束的标志位。
view plaincopy to clipboardprint?
1. static void I2C1WaitTxCplt(void)
2. {
3. uint16_t wTimeOut = 10;
4. while(!gI2C2TxCplt wTimeOut)
5. {
6. HAL_Delay(1);
7. wTimeOut--;
8. }
9. gI2C2TxCplt = false;
10. }
5.修改向ssd1306 写入一个寄存器的功能函数,在这个函数中,我们要组装一个buff 用于向i2c 总线写入数据的,由于向ssd1306 写入寄存器,第一个字节为
0x00,所以组装为[0x00, cmd]。
view plaincopy to clipboardprint?
1. static void OLEDDrvWriteReg(uint8_t ucData)
2. {
3. uint8_t buff[2]= {0x00,0x00};
4. buff[1] = ucData;
5. fsp_err_t err = R_SAU_I2C_Write( g_sau_
i2c_master_ctrl, buff, 2, true);
6. if (FSP_SUCCESS != err)
7. {
8. printf(“%s %drn”, __FUNCTION__, __
LINE__);
9. return;
10. }
11. I2C1WaitTxCplt();
12. }
6.组装向ssd1306 发送一整个buff 的命令:
view plaincopy to clipboardprint?
1. static void OLEDDrvWriteBuf(uint8_t* rbuf,
uint16_t wSize)
2. {
3. fsp_err_t err;
4.
5. // err =R_SAU_I2C_Write( g_sau_i2c_
master_ctrl, 0x40, 1, false);
6. // if(FSP_SUCCESS != err)
7. // printf(“Function:%stLine:%drn”, __
FUNCTION__, __LINE__);
8. rbuf[0] = 0x40;
9. err = R_SAU_I2C_Write( g_sau_i2c_master_
ctrl, rbuf, 1024, true);
10. if(FSP_SUCCESS != err)
11. printf(“Function:%stLine:%drn”, __
FUNCTION__, __LINE__);
12.
13. I2C1WaitTxCplt();
14. }
【注】这里原来使用malloc 进行了重新的内存申请,但是由于这个MCU 的内存有限,我做了申请,好象一直不成功,先写成这样,其实buf 中的0 位是被清除掉了的,所以会有点问题,在后面我将重新这个驱动,这里先实现基本功能。
7.编写测试函数如下:
view plaincopy to clipboardprint?
1. void led_blink(void)
2. {
3.
4. UartDevicesRegister();
5.
6.
7. DisplayDevice *ptDispDev = OLEDGetDevice();
8. if(ptDispDev == NULL)
9. {
10. printf(“Failed to get OLED Display Device!
rn”);
11. return;
12. }
13.
14. ptDispDev- Init(ptDispDev);
15. uint8_t *pBuf = (uint8_t*)ptDispDev- FBbase;
16. while(1)
17. {
18.
19. for(uint16_t i=0; i
dwSize; i++)
20. {
21. pBuf[i] = 0x00;
22. }
23. ptDispDev- Flush(ptDispDev);
24. HAL_Delay(1);
25. for(uint16_t i=0; idwSize; i++)
26. {
27. pBuf[i] = 0xFF;
28. }
29. ptDispDev- Flush(ptDispDev);
30. HAL_Delay(1);
31.
32. }
33. }
其中第一段是向整个屏写入了0x00即全屏为黑色,第二段是写入oxFF 即全白。这样就实现了清屏-》全亮的效果。
3 总结
在面向对象的编程中,对OLED 进行的封装,在使用的过程中,可以实现少量的低层代码的修改即中实现模块化的功能实现。下一步,我将补全字符、图片的功能。
0 条