【极海APM32M3514电机通用评估板】 硬件I2C驱动OLED显示屏
[复制链接]
测试APM32M3514板卡硬件I2C方式驱动OLED显示屏。
一、硬件部分
测试使用PB8和PB9端口
需要将上面的电阻去掉,将PB8和PB9分别连接OLED显示的SCL和SDA引脚,PB8和PB9引脚服复用功能如下表。
二、程序部分
2.1、i2c.c
#include "main.h"
/* Waiting TIMEOUT */
#define I2CT_FLAG_TIMEOUT ((uint32_t)0x1000)
#define I2CT_LONG_TIMEOUT ((uint32_t)(10 * I2CT_FLAG_TIMEOUT))
/*Debug Information output*/
#define I2C_DEBUG_ON 1
#define I2C_ERROR(fmt,arg...) printf("<<-Master-I2C_ERROR->> "fmt"\n",##arg)
static volatile uint32_t I2CTimeout = I2CT_LONG_TIMEOUT;
void init_i2c(void)
{
GPIO_Config_T gpioConfigStruct;
I2C_Config_T i2cConfigStruct;
/* Enable I2C related Clock */
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOB);
RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_I2C);
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
/* Free I2C_SCL and I2C_SDA */
gpioConfigStruct.mode = GPIO_MODE_OUT;
gpioConfigStruct.speed = GPIO_SPEED_50MHz;
gpioConfigStruct.outtype = GPIO_OUT_TYPE_PP;
gpioConfigStruct.pupd = GPIO_PUPD_NO;
gpioConfigStruct.pin = GPIO_PIN_8;
GPIO_Config(GPIOB, &gpioConfigStruct);
gpioConfigStruct.pin = GPIO_PIN_9;
GPIO_Config(GPIOB, &gpioConfigStruct);
GPIO_SetBit(GPIOB, GPIO_PIN_8);
GPIO_SetBit(GPIOB, GPIO_PIN_9);
/* Connect I2C to SCL */
GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_8, GPIO_AF_PIN1);
/* Connect I2C to SDA */
GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_9, GPIO_AF_PIN1);
/* Config I2C GPIO */
gpioConfigStruct.mode = GPIO_MODE_AF;
gpioConfigStruct.speed = GPIO_SPEED_50MHz;
gpioConfigStruct.outtype = GPIO_OUT_TYPE_OD;
gpioConfigStruct.pupd = GPIO_PUPD_NO;
gpioConfigStruct.pin = GPIO_PIN_8;
GPIO_Config(GPIOB, &gpioConfigStruct);
gpioConfigStruct.pin = GPIO_PIN_9;
GPIO_Config(GPIOB, &gpioConfigStruct);
/* Config I2C */
I2C_Reset();
RCM_ConfigI2CCLK(RCM_I2CCLK_SYSCLK);
i2cConfigStruct.ack = I2C_ACK_ENABLE;
i2cConfigStruct.ackaddress = I2C_ACK_ADDRESS_7BIT;
i2cConfigStruct.address1 = 0x30;
i2cConfigStruct.analogfilter = I2C_ANALOG_FILTER_ENABLE;
i2cConfigStruct.digitalfilter = I2C_DIGITAL_FILTER_0;
i2cConfigStruct.mode = I2C_MODE_I2C;
i2cConfigStruct.timing = 0x1042F013;
I2C_Config(&i2cConfigStruct);
/* Enable the I2C Interrupt */
I2C_EnableInterrupt(I2C_INT_RXIE | I2C_INT_ADDRIE | I2C_INT_STOPIE);
/* NVIC configuration */
NVIC_EnableIRQRequest(I2C_IRQn, 1);
/* slave configuration*/
I2C_EnableSlaveByteControl();
I2C_EnableReload();
I2C_EnableStretchClock();
/* Enable I2C */
I2C_Enable();
}
void I2C_Isr(void)
{
uint8_t dat;
if (I2C_ReadIntFlag(I2C_INT_FLAG_ADDR) == SET)
{
I2C_ConfigNumberOfBytes(1);
I2C_ClearIntFlag(I2C_INT_FLAG_ADDR);
}
if (I2C_ReadStatusFlag(I2C_FLAG_RXBNE) == SET)
{
/* I2C_ConfigNumberOfBytes is necessary*/
I2C_ConfigNumberOfBytes(1);
dat = (uint8_t)I2C_RxData();
printf("%c", dat);
}
if (I2C_ReadIntFlag(I2C_INT_FLAG_STOP) == SET)
{
I2C_ClearIntFlag(I2C_INT_FLAG_STOP);
}
}
uint32_t I2C_TIMEOUT_UserCallback(uint8_t errorCode)
{
if (I2C_DEBUG_ON)
{
I2C_ERROR("I2C Wait TIMEOUT! errorCode = %d\r\n", errorCode);
}
return 0;
}
uint32_t I2C_WriteDat(uint8_t DevAddr, uint8_t* pBuffer, uint8_t NByte)
{
uint8_t wNum;
I2CTimeout = I2CT_LONG_TIMEOUT;
/* Wait until I2C is idle */
while (I2C_ReadStatusFlag(I2C_FLAG_BUSY) == SET)
{
init_i2c();
if ((I2CTimeout--) == 0)
{
return I2C_TIMEOUT_UserCallback(1);
}
}
/* Disable I2C interrupt */
I2C_DisableInterrupt(I2C_INT_RXIE | I2C_INT_ADDRIE | I2C_INT_STOPIE);
I2C_DisableReload();
/* I2C Send Configuration*/
I2C_HandlingTransfer(DevAddr, NByte, I2C_RELOAD_MODE_AUTOEND, I2C_GENERATE_START_WRITE);
for(wNum = 0;wNum < NByte;wNum++)
{
I2C_TxData(pBuffer[wNum]);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (I2C_ReadStatusFlag(I2C_FLAG_TXBE) == RESET)
{
if ((I2CTimeout--) == 0)
{
return I2C_TIMEOUT_UserCallback(2);
}
}
}
/* I2C Generate Stop signal */
I2C_EnableGenerateStop();
I2CTimeout = I2CT_LONG_TIMEOUT;
while (I2C_ReadStatusFlag(I2C_FLAG_STOP) == RESET)
{
if ((I2CTimeout--) == 0)
{
return I2C_TIMEOUT_UserCallback(3);
}
}
/* I2C Clear Stop Flag */
I2C_ClearIntFlag(I2C_INT_FLAG_STOP);
return 0;
}
2.2、i2c.h
#ifndef _I2C_H
#define _I2C_H
void init_i2c(void);
void I2C_Isr(void);
uint32_t I2C_WriteDat(uint8_t DevAddr, uint8_t* pBuffer, uint8_t NByte);
#endif
2.3、oled.c
使用的OLED显示屏驱动芯片是SSD1306
#include "main.h"
#include "oled/codetab.h"
#include "i2c/i2c.h"
void oled_WriteByte(uint8_t addr, uint8_t dat)
{
i2c_Start();
i2c_SendByte(0x78);
i2c_WaitAck();
i2c_SendByte(addr);
i2c_WaitAck();
i2c_SendByte(dat);
i2c_WaitAck();
i2c_Stop();
}
void I2C_WriteByte(uint8_t addr, uint8_t dat)
{
uint8_t temp[2];
temp[0] = addr;
temp[1] = dat;
I2C_WriteDat(0x78, temp, 2);
}
void WriteCmd(unsigned char I2C_Command)
{
I2C_WriteByte(0x00, I2C_Command);
}
void WriteDat(unsigned char I2C_Data)
{
I2C_WriteByte(0x40, I2C_Data);
}
void OLED_WrCmd(unsigned char IIC_Command)
{
WriteCmd(IIC_Command);
}
void OLED_Init(void)
{
//i2c_CfgGpio();
APM_DelayMs(100);
WriteCmd(0xAE); //display off
WriteCmd(0x20); //Set Memory Addressing Mode
WriteCmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
WriteCmd(0xb0); //Set Page Start Address for Page Addressing Mode,0-7
WriteCmd(0xc8); //Set COM Output Scan Direction
WriteCmd(0x00); //---set low column address
WriteCmd(0x10); //---set high column address
WriteCmd(0x40); //--set start line address
WriteCmd(0x81); //--set contrast control register
WriteCmd(0xff); //亮度调节 0x00~0xff
WriteCmd(0xa1); //--set segment re-map 0 to 127
WriteCmd(0xa6); //--set normal display
WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
WriteCmd(0x3F); //
WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
WriteCmd(0xd3); //-set display offset
WriteCmd(0x00); //-not offset
WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
WriteCmd(0xf0); //--set divide ratio
WriteCmd(0xd9); //--set pre-charge period
WriteCmd(0x22); //
WriteCmd(0xda); //--set com pins hardware configuration
WriteCmd(0x12);
WriteCmd(0xdb); //--set vcomh
WriteCmd(0x40); //0x20,0.77xVcc
WriteCmd(0x8d); //--set DC-DC enable
WriteCmd(0x14); //
WriteCmd(0xaf); //--turn on oled panel
}
void OLED_SetPos(unsigned char x, unsigned char y)
{
WriteCmd(0xb0+y);
WriteCmd(((x&0xf0)>>4)|0x10);
WriteCmd((x&0x0f)|0x01);
}
void OLED_Fill(unsigned char fill_Data)//全屏填充
{
unsigned char m,n;
for(m=0;m<8;m++)
{
WriteCmd(0xb0+m); //page0-page1
WriteCmd(0x00); //low column start address
WriteCmd(0x10); //high column start address
for(n=0;n<128;n++)
{
WriteDat(fill_Data);
}
}
}
void OLED_CLS(void)//清屏
{
OLED_Fill(0xff);
}
void OLED_ON(void)
{
WriteCmd(0X8D); //设置电荷泵
WriteCmd(0X14); //开启电荷泵
WriteCmd(0XAF); //OLED唤醒
}
void OLED_OFF(void)
{
WriteCmd(0X8D); //设置电荷泵
WriteCmd(0X10); //关闭电荷泵
WriteCmd(0XAE); //OLED休眠
}
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
unsigned char c = 0,i = 0,j = 0;
switch(TextSize)
{
case 1:
{
while(ch[j] != '\0')
{
c = ch[j] - 32;
if(x > 126)
{
x = 0;
y++;
}
OLED_SetPos(x,y);
for(i=0;i<6;i++)
WriteDat(F6x8[c][i]);
x += 6;
j++;
}
}break;
case 2:
{
while(ch[j] != '\0')
{
c = ch[j] - 32;
if(x > 120)
{
x = 0;
y++;
}
OLED_SetPos(x,y);
for(i=0;i<8;i++)
WriteDat(F8X16[c*16+i]);
OLED_SetPos(x,y+1);
for(i=0;i<8;i++)
WriteDat(F8X16[c*16+i+8]);
x += 8;
j++;
}
}break;
}
}
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
{
unsigned char wm=0;
unsigned int adder=32*N;
OLED_SetPos(x , y);
for(wm = 0;wm < 16;wm++)
{
WriteDat(F16x16[adder]);
adder += 1;
}
OLED_SetPos(x,y + 1);
for(wm = 0;wm < 16;wm++)
{
WriteDat(F16x16[adder]);
adder += 1;
}
}
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{
unsigned int j=0;
unsigned char x,y;
if(y1%8==0)
y = y1/8;
else
y = y1/8 + 1;
for(y=y0;y<y1;y++)
{
OLED_SetPos(x0,y);
for(x=x0;x<x1;x++)
{
WriteDat(BMP[j++]);
}
}
}
void oled_test(void)
{
OLED_Init();
OLED_Fill(0x00);
OLED_ShowStr(0,0,"APM32M3514 BOARD",2);
OLED_ShowStr(0,2,"I2C OLED TEST",2);
}
2.4、main.c
int main(void)
{
APM_DelayInit();
APM_DelayMs(5000);
init_usart();
init_led();
init_i2c();
OLED_Init();
oled_test();
while (1)
{
led_on();
APM_DelayMs(200);
led_off();
APM_DelayMs(200);
}
}
三、运行结果
下载程序后,OLED显示屏显示
|