468|1

452

帖子

3

TA的资源

纯净的硅(高级)

楼主
 

【极海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显示屏显示

 

最新回复

看着不错,准备试一下  详情 回复 发表于 2024-12-10 21:14
点赞 关注
 
 

回复
举报

5

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
看着不错,准备试一下
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
立即报名 | 2025 瑞萨电子工业以太网技术日即将开启!
3月-4月 深圳、广州、北京、苏州、西安、上海 走进全国6城
2025瑞萨电子工业以太网技术巡回沙龙聚焦工业4.0核心需求,为工程师与企业决策者提供实时通信技术最佳解决方案。
预报从速,好礼等您拿~

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表