【前言】
在工程https://forum.eepw.com.cn/thread/389948/1的基础之上,添加IIC的OLED驱动,再添加RTC实现时钟的基本驱动。
【步骤】
1、选取IIC的管脚与开发板的EEPROM一致,从开发板的原理图可以看到他为PC6-SCL,PC7为SDA

2、编写IIC初始化。
我这次OLED采取了整个显存,然后用分页进行发送,因此配置为DMA发送:
void OLED_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
I2C_InitTypeDef I2C_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
I2C_DeInit(I2C1);
I2C_StructInit(&I2C_InitStruct);
I2C_InitStruct.I2C_Mode = I2C_MODE_MASTER;
I2C_InitStruct.I2C_OwnAddress = I2C_OWN_ADDRESS;
I2C_InitStruct.I2C_ClockSpeed = 1000000;
I2C_Init(I2C1, &I2C_InitStruct);
I2C_TargetAddressConfig(I2C1, OLED_I2C_ADDRESS);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_4);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_4);
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOC, &GPIO_InitStruct);
I2C_Cmd(I2C1, ENABLE);
}DMA发送函数如下:
void OLED_TxData_DMA_Polling(uint8_t *Buffer, uint8_t Length)
{
DMA_InitTypeDef DMA_InitStruct;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
DMA_DeInit(DMA1_Channel6);
DMA_StructInit(&DMA_InitStruct);
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(I2C1->DR);
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)Buffer;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStruct.DMA_BufferSize = Length;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
DMA_InitStruct.DMA_Priority = DMA_Priority_Low;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_InitStruct.DMA_Auto_Reload = DMA_Auto_Reload_Disable;
DMA_Init(DMA1_Channel6, &DMA_InitStruct);
I2C_DMACmd(I2C1, I2C_DMA_TXEN, ENABLE);
DMA_Cmd(DMA1_Channel6, ENABLE);
while (RESET == DMA_GetFlagStatus(DMA1_FLAG_TC6))
{
}
I2C_DMACmd(I2C1, I2C_DMA_TXEN, DISABLE);
DMA_Cmd(DMA1_Channel6, DISABLE);
}发送命令,只需要发送两个字节,所以不需要采取DMA发送,函数如下:
void I2C_TxData_Polling(uint8_t *Buffer, uint8_t Length)
{
uint8_t i = 0;
for (i = 0; i < Length; i++)
{
I2C_SendData(I2C1, Buffer[i]);
while (RESET == I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE))
{
}
}
I2C_GenerateSTOP(I2C1, ENABLE);
while (RESET == I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE))
{
}
}再编写发送指令与数据的两个关键函数:
/**
* 函 数:OLED写数据
* 参 数:Data 要写入数据的起始地址
* 参 数:Count 要写入数据的数量
* 返 回 值:无
*/
void OLED_WriteData(uint8_t *Data, uint8_t Count)
{
uint8_t dat[1];
dat[0]= 0x40;
OLED_TxData_DMA_Polling(dat,1);
OLED_TxData_DMA_Polling(Data,Count);
I2C_GenerateSTOP(I2C1, ENABLE);
while (RESET == I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE))
{
}
}
/**
* 函 数:OLED写命令
* 参 数:Command 要写入的命令值,范围:0x00~0xFF
* 返 回 值:无
*/
void OLED_WriteCommand(uint8_t Command)
{
uint8_t commadDat[2];
commadDat[0] = 0x00;
commadDat[1] = Command;
I2C_TxData_Polling(commadDat, 2);
}到此IIC的移植就可以了。
【RTC移植】
复制官方示例到工程之中,在mm32f5370_it.c中添加中断回调函数:
void RTC_IRQHandler(void)
{
if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
{
RTC_UpdateCalendar();
RTC_ClearITPendingBit(RTC_IT_SEC);
RTC_WaitForLastTask();
}
}在main.c中添加OLED显示任务:
void led1_task(void *pvParameters)
{
while(1)
{
OLED_Printf(0,16,OLED_8X16,"%02d:%02d:%02d", RTC_Calendar.hour,RTC_Calendar.minute,RTC_Calendar.second);
OLED_Update();
GPIO_WriteBit(GPIOB, GPIO_Pin_15, 0);
vTaskDelay(500);
GPIO_WriteBit(GPIOB, GPIO_Pin_15, 1);
vTaskDelay(500);
}
}实现效果:
下载到开发板后,就可以看到实时运行的时钟了。

我要赚赏金
