2986|0

282

帖子

2

TA的资源

一粒金砂(高级)

楼主
 

【GD32L233C-START评测】5. IIC驱动OLED [复制链接]

本帖讲解的是OLED的驱动。

 

本文只是一个示例,是在我的本系列第二篇帖子的基础上添加的OLED功能,点击跳转:https://bbs.eeworld.com.cn/thread-1192155-1-1.html

 

1. 创建IIC文件

新建文件myiic.c,myiic.h,app_oled.c,app_oled.h四个文件

myiic.c和myiic.h文件主要是软件iic的一些逻辑处理

app_oled.c与app_oled.h是OLED显示以及初始化的一些处理

 

然后将上述创建的四个文件添加到app的group中

2. 编写IIC通信逻辑程序

IIC地相关知识网上有很多相关的讲解也很详细,可以自行搜索了解,本文只讲代码实现。

IIC接线:

SCL  ----   PB10

SDA  ----   PB11

 

 myiic.c

  • #include "myiic.h"
  • #include "systick.h"
  • /* SCL - PB10
  • SDA - PB11
  • */
  • /*init IIC*/
  • void IIC_Init(void)
  • {
  • rcu_periph_clock_enable(RCU_GPIOB);
  • gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_10|GPIO_PIN_11);
  • gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10|GPIO_PIN_11);
  • }
  • /*IIC start signal*/
  • void IIC_Start(void)
  • {
  • SET_IIC_SDA();
  • SET_IIC_SCL();
  • CLR_IIC_SDA();//START:when CLK is high,DATA change form high to low
  • CLR_IIC_SCL();//钳住I2C总线,准备发送或接收数据
  • }
  • /*IIC stop signal*/
  • void IIC_Stop(void)
  • {
  • SET_IIC_SCL();
  • CLR_IIC_SDA();//STOP:when CLK is high DATA change form low to high
  • SET_IIC_SDA();//发送I2C总线结束信号
  • }
  • u8 IIC_Wait_Ack(void)
  • {
  • CLR_IIC_SCL();
  • return 0;
  • }
  • /*ack signal*/
  • void IIC_Ack(void)
  • {
  • CLR_IIC_SCL();
  • SDA_OUT();
  • CLR_IIC_SDA();
  • SET_IIC_SCL();
  • CLR_IIC_SCL();
  • }
  • //不产生ACK应答
  • void IIC_NAck(void)
  • {
  • CLR_IIC_SCL();
  • SDA_OUT();
  • SET_IIC_SDA();
  • SET_IIC_SCL();
  • CLR_IIC_SCL();
  • }
  • //IIC发送一个字节
  • //返回从机有无应答
  • //1,有应答
  • //0,无应答
  • void IIC_Send_Byte(u8 txd)
  • {
  • u8 t;
  • CLR_IIC_SCL();//拉低时钟开始数据传输
  • for(t=0;t<8;t++)
  • {
  • if((txd&0x80)>>7)
  • SET_IIC_SDA();
  • else
  • CLR_IIC_SDA();
  • txd<<=1;
  • SET_IIC_SCL();
  • CLR_IIC_SCL();
  • }
  • }
  • //读1个字节,ack=1时,发送ACK,ack=0,发送nACK
  • u8 IIC_Read_Byte(unsigned char ack)
  • {
  • unsigned char i,receive=0;
  • SDA_IN();//SDA设置为输入
  • for(i=0;i<8;i++ )
  • {
  • CLR_IIC_SCL();
  • SET_IIC_SCL();
  • receive<<=1;
  • if(READ_SDA)
  • receive++;
  • }
  • if (!ack)
  • IIC_NAck();//发送nACK
  • else
  • IIC_Ack(); //发送ACK
  • return receive;
  • }

myiic.h

  • #ifndef __MYIIC_H
  • #define __MYIIC_H
  • #include "gd32l23x.h"
  • typedef uint8_t u8;
  • typedef uint16_t u16;
  • typedef uint32_t u32;
  • //IO操作函数
  • #define SET_IIC_SCL() gpio_bit_set(GPIOB, GPIO_PIN_10)//输出1
  • #define CLR_IIC_SCL() gpio_bit_reset(GPIOB, GPIO_PIN_10)//输出0
  • #define SET_IIC_SDA() gpio_bit_set(GPIOB, GPIO_PIN_11)//输出1
  • #define CLR_IIC_SDA() gpio_bit_reset(GPIOB, GPIO_PIN_11)//输出0
  • #define READ_SDA gpio_input_bit_get(GPIOB, GPIO_PIN_11) //输入SDA
  • //IO方向设置
  • #define SDA_IN() gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_11)//配置为输入
  • #define SDA_OUT() { gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_11);\
  • gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11);} //配置为输出
  • //IIC所有操作函数
  • void IIC_Init(void); //初始化IIC的IO口
  • void IIC_Start(void); //发送IIC开始信号
  • void IIC_Stop(void); //发送IIC停止信号
  • void IIC_Send_Byte(unsigned char txd); //IIC发送一个字节
  • unsigned char IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
  • unsigned char IIC_Wait_Ack(void); //IIC等待ACK信号
  • void IIC_Ack(void); //IIC发送ACK信号
  • void IIC_NAck(void); //IIC不发送ACK信号
  • void IIC_Write_One_Byte(unsigned char daddr,unsigned char addr,unsigned char data);
  • unsigned char IIC_Read_One_Byte(unsigned char daddr,unsigned char addr);
  • #endif

3. OLED显示逻辑程序

OLED的SCL引脚   ---  PB10

OLED的SDA引脚  ---  PB11

 

app_oled.c

  • //OLED
  • #include "codetab.h"
  • #include "app_oled.h"
  • #include "myiic.h"
  • #include "systick.h"
  • u8 OLED_GRAM[128][8];
  • /*********************OLED写数据函数************************************/
  • void OLED_WrDat(unsigned char IIC_Data)
  • {
  • IIC_Start();
  • IIC_Send_Byte(0x78);
  • IIC_Wait_Ack();
  • IIC_Send_Byte(0x40); //write data
  • IIC_Wait_Ack();
  • IIC_Send_Byte(IIC_Data);
  • IIC_Wait_Ack();
  • IIC_Stop();
  • }
  • /*********************OLED写命令函数************************************/
  • void OLED_WrCmd(unsigned char IIC_Command)
  • {
  • IIC_Start();
  • IIC_Send_Byte(0x78); //Slave address,SA0=0
  • IIC_Wait_Ack();
  • IIC_Send_Byte(0x00); //write command
  • IIC_Wait_Ack();
  • IIC_Send_Byte(IIC_Command);
  • IIC_Wait_Ack();
  • IIC_Stop();
  • }
  • //--------------------------------------------------------------
  • // Prototype : void OLED_OFF(void)
  • // Calls :
  • // Parameters : none
  • // Description : 让OLED休眠 -- 休眠模式下,OLED功耗不到10uA
  • //--------------------------------------------------------------
  • void OLED_OFF(void)
  • {
  • OLED_WrCmd(0X8D);
  • OLED_WrCmd(0X10);
  • OLED_WrCmd(0XAE);
  • }
  • //--------------------------------------------------------------
  • // Prototype : void OLED_ON(void)
  • // Calls :
  • // Parameters : none
  • // Description : 将OLED从休眠中唤醒
  • //--------------------------------------------------------------
  • void OLED_ON(void)
  • {
  • OLED_WrCmd(0X8D);
  • OLED_WrCmd(0X14);
  • OLED_WrCmd(0XAF);
  • }
  • //x1,y1,x2,y2 填充区域的对角坐标
  • //确保x1<=x2;y1<=y2 0<=x1<=127 0<=y1<=63
  • //dot:0,清空;1,填充
  • void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot)
  • {
  • u8 x,y;
  • for(x=x1;x<=x2;x++)
  • for(y=y1;y<=y2;y++)
  • OLED_DrawPoint(x,y,dot);
  • OLED_Refresh_Gram();//更新显示
  • }
  • //清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
  • void OLED_Clear(void)
  • {
  • u8 i,n;
  • for(i=0;i<8;i++)
  • for(n=0;n<128;n++)
  • OLED_GRAM[n][i]=0X00;
  • OLED_Refresh_Gram();//更新显示
  • }
  • /*********************OLED初始化************************************/
  • void OLED_Init(void)
  • {
  • // IIC_Init();
  • // delay_1ms(100);
  • OLED_WrCmd(0xAE); //关闭显示
  • OLED_WrCmd(0xD5); //设置时钟分频因子,震荡频率
  • OLED_WrCmd(80); //[3:0],分频因子;[7:4],震荡频率
  • OLED_WrCmd(0xA8); //设置驱动路数
  • OLED_WrCmd(0X3F); //默认0X3F(1/64)
  • OLED_WrCmd(0xD3); //设置显示偏移
  • OLED_WrCmd(0X00); //默认为0
  • OLED_WrCmd(0x40); //设置显示开始行 [5:0],行数.
  • OLED_WrCmd(0x8D); //电荷泵设置
  • OLED_WrCmd(0x14); //bit2,开启/关闭
  • OLED_WrCmd(0x20); //设置内存地址模式
  • OLED_WrCmd(0x02); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
  • OLED_WrCmd(0xA1); //段重定义设置,bit0:0,0->0;1,0->127;
  • OLED_WrCmd(0xC0); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
  • OLED_WrCmd(0xDA); //设置COM硬件引脚配置
  • OLED_WrCmd(0x12); //[5:4]配置
  • OLED_WrCmd(0x81); //对比度设置
  • OLED_WrCmd(0xEF); //1~255;默认0X7F (亮度设置,越大越亮)
  • OLED_WrCmd(0xD9); //设置预充电周期
  • OLED_WrCmd(0xf1); //[3:0],PHASE 1;[7:4],PHASE 2;
  • OLED_WrCmd(0xDB); //设置VCOMH 电压倍率
  • OLED_WrCmd(0x30); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
  • OLED_WrCmd(0xA4); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
  • OLED_WrCmd(0xA6); //设置显示方式;bit0:1,反相显示;0,正常显示
  • OLED_WrCmd(0xAF); //开启显示
  • OLED_Clear();
  • }
  • //更新显存到LCD
  • void OLED_Refresh_Gram(void)
  • {
  • u8 i,n;
  • for(i=0;i<8;i++)
  • {
  • OLED_WrCmd (0xb0+i); //设置页地址(0~7)
  • OLED_WrCmd (0x00); //设置显示位置—列低地址
  • OLED_WrCmd (0x10); //设置显示位置—列高地址
  • for(n=0;n<128;n++)
  • OLED_WrDat(OLED_GRAM[n][i]);
  • }
  • }
  • //画点
  • //x:0~127
  • //y:0~63
  • //t:1 填充 0,清空
  • void OLED_DrawPoint(u8 x,u8 y,u8 t)
  • {
  • u8 pos,bx,temp=0;
  • if(x>127||y>63)return;//超出范围了.
  • pos=7-y/8;
  • bx=y%8;
  • temp=1<<(7-bx);
  • if(t)
  • OLED_GRAM[x][pos]|=temp;
  • else
  • OLED_GRAM[x][pos]&=~temp;
  • }
  • //在指定位置显示一个字符,包括部分字符
  • //x:0~127
  • //y:0~63
  • //mode:0,反白显示;1,正常显示
  • //size:选择字体 16/12
  • void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)
  • {
  • u8 temp,t,t1;
  • u8 y0=y;
  • u8 csize=(size/8+((size%8)?1:0))*(size/2); //得到字体一个字符对应点阵集所占的字节数
  • chr=chr-' ';//得到偏移后的值
  • for(t=0;t<csize;t++)
  • {
  • if(size==12)temp=asc2_1206[chr][t]; //调用1206字体
  • else if(size==16)temp=asc2_1608[chr][t]; //调用1608字体
  • else if(size==24)temp=asc2_2412[chr][t]; //调用2412字体
  • else return; //没有的字库
  • for(t1=0;t1<8;t1++)
  • {
  • if(temp&0x80)
  • OLED_DrawPoint(x,y,mode);
  • else OLED_DrawPoint(x,y,!mode);
  • temp<<=1;
  • y++;
  • if((y-y0)==size)
  • {
  • y=y0;
  • x++;
  • break;
  • }
  • }
  • }
  • }
  • //m^n函数
  • u32 mypow(u8 m,u8 n)
  • {
  • u32 result=1;
  • while(n--)result*=m;
  • return result;
  • }
  • //显示2个数字
  • //x,y :起点坐标
  • //len :数字的位数
  • //size:字体大小
  • //mode:模式 0,填充模式;1,叠加模式
  • //num:数值(0~4294967295);
  • void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size)
  • {
  • u8 t,temp;
  • u8 enshow=0;
  • for(t=0;t<len;t++)
  • {
  • temp=(num/mypow(10,len-t-1))%10;
  • if(enshow==0&&t<(len-1))
  • {
  • if(temp==0)
  • {
  • OLED_ShowChar(x+(size/2)*t,y,'0',size,1);
  • continue;
  • }else enshow=1;
  • }
  • OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1);
  • }
  • }
  • //显示字符串
  • //x,y:起点坐标
  • //size:字体大小
  • //*p:字符串起始地址
  • void OLED_ShowString(u8 x,u8 y,const u8 *p,u8 size,uint8_t mode)
  • {
  • while((*p<='~')&&(*p>=' '))//判断是不是非法字符!
  • {
  • if(x>(128-(size/2))){x=0;y+=size;}
  • if(y>(64-size)){y=x=0;OLED_Clear();}
  • OLED_ShowChar(x,y,*p,size,mode);
  • x+=size/2;
  • p++;
  • }
  • }
  • //显示图形
  • //得到字体一个字符对应点阵集所占的字节数
  • //len--传入的数据的总长度
  • void OLED_ShowBMP(u8 x,u8 y,u8 mode,u8 bmp[][16],u32 len)
  • {
  • u16 t,t1;
  • u8 y0=y;
  • u8 temp;
  • u16 len2=len/16; //数组的列数
  • for(t=0;t<len;t++)
  • {
  • temp=bmp[0][t];
  • for(t1=0;t1<8;t1++)
  • {
  • if(temp&0x80)
  • OLED_DrawPoint(x,y,mode);
  • else OLED_DrawPoint(x,y,!mode);
  • temp<<=1;
  • y++;
  • if((y-y0) == len2)
  • {
  • y = y0;
  • x ++;
  • break;
  • }
  • }
  • }
  • }

 

app_oled.h

  • #ifndef _APP_OLED_H_
  • #define _APP_OLED_H_
  • #include "stdint.h"
  • extern void OLED_Init(void);
  • extern void OLED_Fill(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2,unsigned char dot);
  • extern void OLED_Clear(void);
  • extern void OLED_Refresh_Gram(void);
  • extern void OLED_DrawPoint(unsigned char x,unsigned char y,unsigned char t);
  • extern void OLED_ShowChar(unsigned char x,unsigned char y,unsigned char chr,unsigned char size,unsigned char mode);
  • extern void OLED_ShowNum(unsigned char x,unsigned char y,unsigned int num,unsigned char len,unsigned char size);
  • extern void OLED_ShowString(unsigned char x,unsigned char y,const unsigned char *p,unsigned char size,unsigned char mode);
  • extern void OLED_ShowBMP(unsigned char x,unsigned char y,unsigned char mode,unsigned char bmp[][16],unsigned int len);
  • #endif

上述代码实现了一些显示字符的函数封装:字符显示,字符串显示,数字显示,清空OLED,以及刷新OLED等

 

4. main函数实现OLED字符串显示

在main() while循环之前加上如下语句:

  • OLED_ShowString(0, 0, "GD32L233C-START", 16, 1);
  • OLED_ShowString(0, 16, "EEWORLD", 24, 0);
  • OLED_Refresh_Gram();

含义是:

1). 在0,0坐标上以16像素点大小显示GD32L233C-START这个字符串,最后一个参数1表示写得字符不取反

2). 在0,16这个坐标上以24像素点显示EEWORLD这个字符串,最后一个参数0表示取反显示

3). 将上述显示的字符串写到OLED显示屏上

 

5. 显示效果

 

 

 

 

 

此帖出自GD32 MCU论坛
点赞 关注(2)
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
推荐帖子
硬件工程师必备知识

硬件工程师必须知道的知识目的:基于实际经验与实际项目详细理解并掌握成为合格的硬件工程师的最基本知识。 1) 基本设计规范 2 ...

单片机控制飞梭的原理

有搞过这方面的朋友吗?能否给个AVR控制这个元件的原理

谈F28M35的M3侧的blink例程

从简单的谈起吧。 1、程序先进行了HWREG(SYSCTL_MWRALLOW) = 0xA5A5A5A5; 因为 //必须写入0xA5A5A5A5,之后才能够改写一些 ...

纯手工DIY微波PLL频率源,全部公开多图!!!。。。

本帖最后由 RF-刘海石 于 2014-11-23 16:55 编辑 频率源大家都晓得,是通信中的重要的组件,也可以这么说是接收机和发 ...

为小米蓝牙鼠标增加充电功能

现在很多鼠标都支持USB充电了,这样不用担心用着用着没有电,就要换电池了。 为了节约笔记本的USB,我用了一个小米蓝牙鼠标 ...

每逢大暴雨就面临时不时断网的我

报个坐标,福州乡下的一个小县城下的一个小嘎达镇。。。。每逢大暴雨天气,网络就断断续续断断续续,宽带网络这样,手机信号也这 ...

印刷电路板的焊接表面:HAL 无铅

印刷电路板的焊接表面:HAL 无铅 HAL 无铅焊接表面提供所有表面的最佳可焊性,但锡层的厚度各不相同。 642848 < ...

【回顾2022展望2023】安全第一健康是福

回顾2022,觉得最重要的两点就是标题:安全第一,健康是福。 这一年,我们这一个小小的小县城,火灾,车祸发生了不知多少起。 ...

我在AD中创建PCB文件时提示这个,怎么解决?

798527

电感有耐压值吗?

为什么很多电感资料没有耐压值呢,是大家都默认电感耐压很高,不需要考虑吗?

关闭
站长推荐上一条 1/10 下一条
【干货上新】电源解决方案和技术第二趴 | DigiKey 应用探索站
当月好物、电源技术资源、特色活动、DigiKey在线实用工具,干货多多~

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

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

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

北京市海淀区中关村大街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
快速回复 返回顶部 返回列表