【前言】
在武汉沁源的智小车上,使用的OLED驱动用的是软件模拟IIC,我这篇将分享将其代码修改为硬件IIC驱动。并在饭盒派上实现显示温度测量。
【硬件选择】
饭盒派有一个OLED接口,硬件接到了SCL(PB6),SDA(PB7),此次工程也选择这两个IO做为硬件IIC的驱动IO。
【驱动移植】
找到智能小车的驱动,把他的OLED.c/h以及字库OLED_date.c/h移植到前面我做好的温度测量工程中(详见帖子:【CW32L012】5、芯片温度值测量-电子产品世界论坛)

【代码修改】
1、将其模拟IIC的代码去除。
2、添加SCL、SDA的IO配置函数,代码如下:
void OLED_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
/* 开启GPIOB时钟 */
__SYSCTRL_GPIOB_CLK_ENABLE();
/* 复用引脚为IIC */
PB06_AFx_I2C1SCL();
PB07_AFx_I2C1SDA();
/* 配置IO的为输出模式 */
GPIO_InitStructure.Pins = I2C1_SCL_GPIO_PIN | I2C1_SDA_GPIO_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_Init(I2C1_SCL_GPIO_PORT, &GPIO_InitStructure);
}3、添加IIC初始化函数:
void OLED_I2C_Config(void)
{
I2C_DeInit(CW_I2C1);
I2C_MasterConfigTypeDef I2C_InitStruct;
I2C_MasterInitDefault(&I2C_InitStruct); // I2C初始化为默认值
I2C_MasterInit(CW_I2C1, &I2C_InitStruct, 96000000UL); // I2C配置
I2C_MasterCmd(CW_I2C1, ENABLE); // I2C模块使能
}这里说明一下,武汉芯源的固件库做得非常不错,只需要把默认的结构体,与CPU工作时钟传进去,就帮配置好了。当然如何想配置更加详细的IIC总线,可以将I2C_Initstruct进行个性化的传参,达到你想要的结果。
4、修改OLED发送命令的函数。
使用过OLED(芯片为ssd1306)的都知道,发送指令的函数是在发送从机地址(0x3C),之后发送0x00,再发送指令代码,因此我编写代码如下:
void OLED_WriteCommand(uint8_t Command)
{
uint8_t tx_buf[2];
tx_buf[0] = 0x00; //发送command 第1位为0x00
tx_buf[1] = Command; //接着发送命令
I2C_MasterSendDataToSlave(CW_I2C1, 0x3C, tx_buf, 2);
}5、修改OLED发送数据的函数
发送数据,在我们发送从机地址后,跟着发送0x40,再接着发送我们需要发送的数据,因此,需要重新生成一个数组,在我们发送数据的基础上+1,然后把数据放进新数组里,再接着发送(有点浪费资源),在我的另一篇帖子里,有更加好的解决方法,详见:【分享开发笔记,赚取电动螺丝刀】OLED刷新终极优化-电子产品世界论坛
代码如下:
void OLED_WriteData(uint8_t *Data, uint8_t Count)
{
uint8_t tx_buf[Count+1];
tx_buf[0] = 0x40;
for(uint8_t i=1;i<Count+1;i++)
{
tx_buf[i] = Data[i-1];
}
I2C_MasterSendDataToSlave(CW_I2C1, 0x3C, tx_buf, Count+1);
}好了所有移植就完成啦,非常简单。
在app.c中添加oled的初始化代码,把电压值打印到屏中:
#include "app.h"
#include "bsp_adc.h"
#include "cw32l012_systick.h"
#include "cw32l012_adc.h"
#include "OLED.h"
void Run(void)
{
uint32_t valueAdcAcc;
uint16_t valueAdc;
float fTsDegree, fVoltage;
ADC_Temp_Init();
CW_ADC1->START_f.START = 1; //开始转换
OLED_Init();
while(1)
{
if(CW_ADC1->ISR_f.EOS)
{
valueAdc = CW_ADC1->RESULT1_f.RESULT; //获取1.2V电压转换值
fVoltage = ADC_BgrResult2Avcc(valueAdc); //计算出ADD电压值
valueAdc = CW_ADC1->RESULT0_f.RESULT; //获取温度值计数值
fTsDegree = ADC_GetTs(fVoltage, valueAdc); //计算出温度
printf("The Temperature is %2f\r\n", fTsDegree);
printf("The Reference voltage is %2f\r\n", fVoltage);
OLED_Printf(1,0,OLED_6X8,"Hello");
OLED_Printf(1,16,OLED_6X8,"Temp %.2f", fTsDegree);
OLED_Printf(1,24,OLED_6X8,"voltage %.2f", fVoltage);
OLED_Update();
}
SysTickDelay(1000);
}
}【实验效果】

我把源代码上传,大家有需要OLED屏驱动的可以自取!
OLED.zip