STC32G 系列的单片机内部集成了一个 I2C 串行总线控制器。I2C 是一种高速同步通讯总线,通讯使用 SCL(时钟线)和 SDA(数据线)两线进行同步通讯。对于 SCL 和 SDA 的端口分,STC32G 系列的单片机提供了切换模式,可将 SCL 和 SDA 切换到不同的 I/O 口上,以方便用户将一组 I2C 总线当作多组进行分时复用。与标准 I2C 协议相比较,忽略了如下两种机制:

 发送起始信号(START)后不进行仲裁
 时钟信号(SCL)停留在低电平时不进行超时检测

STC32G 系列的 I2C 总线提供了两种操作模式:主机模式(SCL 为输出口,发送同步时钟信号)和从机模式(SCL 为输入口,接收同步时钟信号),这里要实现oled12864的显示,所以用到的是主机模式。

如上图所示,要用到的初始化函数为:void    I2C_Init(I2C_InitTypeDef *I2Cx),在主机模式下要对结构体的属性进行设置的只有:I2C_InitStructure.I2C_Mode,I2C_InitStructure.I2C_Enable, I2C_InitStructure.I2C_Speed,I2C_InitStructure.I2C_MS_WDTA,

从stc32g的数据手册知道内部集成的I2C总线功能是有规定引脚的,这里我们选择SCL:P25,SDA:P24:

所以,我们的I2C初始化函数为:

void I2C_config(void)
{I2C_InitTypeDef        I2C_InitStructure;I2C_InitStructure.I2C_Mode      = I2C_Mode_Master;       //主从选择   I2C_Mode_Master, I2C_Mode_SlaveI2C_InitStructure.I2C_Enable    = ENABLE;                          //I2C功能使能,   ENABLE, DISABLEI2C_InitStructure.I2C_Speed     = 13;                                  //I2C总线速度,   0~63I2C_InitStructure.I2C_MS_WDTA   = DISABLE;                            //使能主机自动发送设置,   ENABLE, DISABLEI2C_Init(&I2C_InitStructure);I2C_SW(I2C_P24_P25);                    //I2C_P14_P15,I2C_P24_P25,I2C_P76_P77,I2C_P33_P32
}

接下来看一下官方的库函数中的STC32G_I2C.c文件

//========================================================================
// 函数: u8   Get_MSBusy_Status (void)
// 描述: 获取主机忙碌状态.
// 参数: none.
// 返回: 主机忙碌状态.
// 版本: V1.0, 2012-11-22
//========================================================================
u8 Get_MSBusy_Status(void)
{return (I2CMSST & 0x80);
}//========================================================================
// 函数: void Wait (void)
// 描述: 等待主机模式I2C控制器执行完成I2CMSCR.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2012-11-22
//========================================================================
void Wait()
{while (!(I2CMSST & 0x40));I2CMSST &= ~0x40;
}//========================================================================
// 函数: void Start (void)
// 描述: I2C总线起始函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void Start()
{I2CMSCR = 0x01;                         //发送START命令Wait();
}//========================================================================
// 函数: void SendData (char dat)
// 描述: I2C发送一个字节数据函数.
// 参数: 发送的数据.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void SendData(char dat)
{I2CTXD = dat;                           //写数据到数据缓冲区I2CMSCR = 0x02;                         //发送SEND命令Wait();
}//========================================================================
// 函数: void RecvACK (void)
// 描述: I2C获取ACK函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void RecvACK()
{I2CMSCR = 0x03;                         //发送读ACK命令Wait();
}//========================================================================
// 函数: char RecvData (void)
// 描述: I2C读取一个字节数据函数.
// 参数: none.
// 返回: 读取数据.
// 版本: V1.0, 2020-09-15
//========================================================================
char RecvData()
{I2CMSCR = 0x04;                         //发送RECV命令Wait();return I2CRXD;
}//========================================================================
// 函数: void SendACK (void)
// 描述: I2C发送ACK函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void SendACK()
{I2CMSST = 0x00;                         //设置ACK信号I2CMSCR = 0x05;                         //发送ACK命令Wait();
}//========================================================================
// 函数: void SendNAK (void)
// 描述: I2C发送NAK函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void SendNAK()
{I2CMSST = 0x01;                         //设置NAK信号I2CMSCR = 0x05;                         //发送ACK命令Wait();
}//========================================================================
// 函数: void Stop (void)
// 描述: I2C总线停止函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void Stop()
{I2CMSCR = 0x06;                         //发送STOP命令Wait();
}//========================================================================
// 函数: void SendCmdData (u8 cmd, u8 dat)
// 描述: I2C发送一个字节数据函数.
// 参数: 命令/数据.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void SendCmdData(u8 cmd, u8 dat)
{I2CTXD = dat;                           //写数据到数据缓冲区I2CMSCR = cmd;                          //设置命令Wait();
}//========================================================================
// 函数: void I2C_WriteNbyte(u8 addr, u8 *p, u8 number)
// 描述: I2C写入数据函数.
// 参数: addr: 指定地址, *p写入数据存储位置, number写入数据个数.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void I2C_WriteNbyte(u8 addr, u8 *p, u8 number)  /*  WordAddress,First Data Address,Byte lenth   */
{Start();                                //发送起始命令SendData(SLAW);                         //发送设备地址+写命令RecvACK();SendData(addr);                         //发送存储地址RecvACK();do{SendData(*p++);RecvACK();}while(--number);Stop();                                 //发送停止命令
}//========================================================================
// 函数: void I2C_ReadNbyte(u8 addr, u8 *p, u8 number)
// 描述: I2C读取数据函数.
// 参数: addr: 指定地址, *p读取数据存储位置, number读取数据个数.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void I2C_ReadNbyte(u8 addr, u8 *p, u8 number)   /*  WordAddress,First Data Address,Byte lenth   */
{Start();                                //发送起始命令SendData(SLAW);                         //发送设备地址+写命令RecvACK();SendData(addr);                         //发送存储地址RecvACK();Start();                                //发送起始命令SendData(SLAR);                         //发送设备地址+读命令RecvACK();do{*p = RecvData();p++;if(number != 1) SendACK();          //send ACK}while(--number);SendNAK();                              //send no ACK    Stop();                                 //发送停止命令
}

这个文件中有我们所熟知的I2C通信所必须的Wait(),Start(),Senddata()等的函数,它们的用法用过I2C通信的相信都知道了,但在STC32G_I2C.h这个头文件中只包含了以下几个函数的声明:

void I2C_Init(I2C_InitTypeDef *I2Cx);
void    I2C_WriteNbyte(u8 addr, u8 *p, u8 number);
void    I2C_ReadNbyte( u8 addr, u8 *p, u8 number);
u8 Get_MSBusy_Status(void);
void SendCmdData(u8 dat, u8 cmd);

所以我们使用I2C总线有两种方法,第一种是把所有函数的声明都添加到头文件中,这样就可以调用Wait(),Start(),Senddata()等函数;第二种方法是用头文件中给的函数,也就是I2C_WriteNbyte(u8 addr, u8 *p, u8 number)这个函数。这里我们详细讲第二种方法,I2C_WriteNbyte()这个函数需要输入三个参数,u8 addr, u8 *p, u8 number,这里指定地址我们可以理解为对oled是进行写数据操纵还是写命令操作,所以输入时输入以下两个中一个就行:

#define OLED_CMD  0x00   //写命令
#define OLED_DATA 0x40  //写数据

p为要输入数据或命令的指针,可以一次输入多个数据,number为数据数。这里还有一点要注意的:SLAW的宏定义需要修改如下:

#define SLAW    0x78

然后就可以移植中景园的oled51例程,需要修改的只有OLED_WR_Byte()这一函数:

void OLED_WR_Byte(u8 dat,u8 mode)
{#if 0Start();SendData(0x78);RecvACK();SendData(mode);RecvACK();SendData(dat);SendNAK();Stop();#elseI2C_WriteNbyte(mode,&dat,1);#endif}

然后就可以显示啦

还有两点要注意的是,这里的memory mode 需要修改一下:

原因可能是库函数中定义的常量太多导致无法显示,修改后就可正常显示。而另一个问题是我发现在单独显示字符串,也就是在主函数中只调用OLED_ShowString()这一函数时oled无法显示,并且好像连单片机都无法正常使用,有大神路过的话希望能帮忙解惑一下。

同样的,项目我放在主页资源上。

STC32G12K128内部集成的I2C总线实现oled12864显示相关推荐

  1. 干货总结:I2C总线详细要点

    [导读] 前文总结了单片机串口个人认为值得注意的一些要点,本文来梳理一下 I2C 总线的一些要点.这个题目有点大,本文对于 I2C 其实很多地方也没整清楚,只为了与前文形成系列,如果大家有补充欢迎留言 ...

  2. arm linux i2c 总线驱动,ARM-Linux中I2C总线驱动开发

    摘  要: 针对I2C总线的特点,Linux内核中定义了I2C驱动体系结构.在分析Linux的I2C总线驱动体系结构基础上,介绍了在S3C2410中设计I2C总线驱动的方法. 关键词: ARM-Lin ...

  3. SylixOS iMX6平台I2C总线驱动

    原理概述 I2C总线驱动概述 I2C总线驱动是I2C适配器的软件实现,提供I2C适配器与从设备间完成数据通信的能力,比如起始,停止,应答信号和MasterXfer的实现函数.驱动程序包含初始化I2C总 ...

  4. 总线协议之I2C总线时序

    路漫漫其修远兮,吾将上下而求索 I2C总线时序 http://hi.baidu.com/yangfengyuk/blog/item/16e586fa52fd211f6d22ebfe.html/cmti ...

  5. I2C总线 | 百度百科

    目录 工作原理 特征 数据传输 字节格式 应答响应 时钟同步 模式 快速模式 高速模式 参考资料 I2C总线是由Philips公司开发的一种简单.双向二线制同步串行总线.它只需要两根线即可在连接于总线 ...

  6. I2C详解(3) I2C总线的规范以及用户手册(2) I2C其他的总线协议以及总线速度

    I2C详解(3) I2C总线的规范以及用户手册(2) I2C 其他的总线协议以及总线速度 I2C详解(1) 一文快速了解I2C的工作原理 I2C详解(2) I2C总线的规范以及用户手册(1) I2C ...

  7. 【InterFace】I2C 总线详述

    背景 昨天出去了一趟,人问:你熟悉什么?答:软硬件.结果,好尴尬. 硬件一般都做什么内容? 答:电源设计. 能说下升压.降压电路是怎么实现的吗? 答:不能.(Ps:后续增加 电源设计原理) 通讯都用到 ...

  8. Linux I2C总线详解

    概述: 1.I2C概念 2.I2C硬件结构图 3.I2C总线初始化 4.I2C控制器device 节点添加及driver注册 5.I2C设备节点添加及driver注册 5.adapter设备及驱动添加 ...

  9. SPI与I2C总线协议

    目录: 一.SPI总线协议 1.什么是SPI 2.技术性能 3.接口定义与硬件连接 4.内部结构 5.传输时序 6.高速SPI 1)硬件电路   2)1MHz SPI传输问题 二.I2C总线协议 1. ...

最新文章

  1. qt获取窗口的右上角位置_如何获得 Qt窗口部件在主窗口中的位置--确定鼠标是否在某一控件上与在控件上的位置...
  2. Sizeof与Strlen的区别与联系(转)
  3. Android:禁用listView上的突出显示单击
  4. SAP-PM 的工具管理篇
  5. PO RELEASE 采购订单审核(支持多级审核)
  6. gnuradio android手机,如何搭配USRP在安卓设备上搭建GNU Radio
  7. CodeForces - 1373E Sum of Digits(贪心)
  8. 使用Matlab(R2018b)画复杂函数的图形(网格图meshgrid)及等高线contour
  9. Java面向对象编程篇6——注解与反射
  10. 源头防堵信息泄露 监管拟全面推行支付标记化
  11. memcached(十)动态扩容
  12. linux目录存 xml文件,将IDEA maven项目中src源代码下的xml等资源文件编译进classes文件夹...
  13. 生成解析器:Fsyacc
  14. 【工具向】分析FGUI依赖关系工具
  15. ubuntu给手机刷机安卓8.0 ROOT+Xposed+JustTrustMe+Kali NetHunter
  16. 螺旋分级机与水力分级机间的优缺点
  17. 关于长江的题目_高中优秀议论文题目【高中关于长江的作文题目加优秀范文】...
  18. js版【微信机器人】——wechat-robot
  19. 使用RocketMQ进行银行转账
  20. 【渝粤题库】国家开放大学2021春2114人体解剖生理学题目

热门文章

  1. Hibernate笔记辅助代码
  2. 关于fork的一些知识
  3. kappa值大于多少有多重共线性
  4. W7级别的服务器系统,w7系统的云服务器
  5. C语言程序设计与实践 北理工 1. 达拉崩吧的酒宴
  6. M401 Emuelec 连接蓝牙手柄
  7. 关于梦行monxin网络商城如何查询开店邀请码的方法
  8. Windows Server 2016 安装步骤
  9. AB上的脚本引用丢失,The referenced script is missing!
  10. The 6th Zhejiang Provincial Collegiate Programming Contest