STC32G12K128内部集成的I2C总线实现oled12864显示
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显示相关推荐
- 干货总结:I2C总线详细要点
[导读] 前文总结了单片机串口个人认为值得注意的一些要点,本文来梳理一下 I2C 总线的一些要点.这个题目有点大,本文对于 I2C 其实很多地方也没整清楚,只为了与前文形成系列,如果大家有补充欢迎留言 ...
- arm linux i2c 总线驱动,ARM-Linux中I2C总线驱动开发
摘 要: 针对I2C总线的特点,Linux内核中定义了I2C驱动体系结构.在分析Linux的I2C总线驱动体系结构基础上,介绍了在S3C2410中设计I2C总线驱动的方法. 关键词: ARM-Lin ...
- SylixOS iMX6平台I2C总线驱动
原理概述 I2C总线驱动概述 I2C总线驱动是I2C适配器的软件实现,提供I2C适配器与从设备间完成数据通信的能力,比如起始,停止,应答信号和MasterXfer的实现函数.驱动程序包含初始化I2C总 ...
- 总线协议之I2C总线时序
路漫漫其修远兮,吾将上下而求索 I2C总线时序 http://hi.baidu.com/yangfengyuk/blog/item/16e586fa52fd211f6d22ebfe.html/cmti ...
- I2C总线 | 百度百科
目录 工作原理 特征 数据传输 字节格式 应答响应 时钟同步 模式 快速模式 高速模式 参考资料 I2C总线是由Philips公司开发的一种简单.双向二线制同步串行总线.它只需要两根线即可在连接于总线 ...
- I2C详解(3) I2C总线的规范以及用户手册(2) I2C其他的总线协议以及总线速度
I2C详解(3) I2C总线的规范以及用户手册(2) I2C 其他的总线协议以及总线速度 I2C详解(1) 一文快速了解I2C的工作原理 I2C详解(2) I2C总线的规范以及用户手册(1) I2C ...
- 【InterFace】I2C 总线详述
背景 昨天出去了一趟,人问:你熟悉什么?答:软硬件.结果,好尴尬. 硬件一般都做什么内容? 答:电源设计. 能说下升压.降压电路是怎么实现的吗? 答:不能.(Ps:后续增加 电源设计原理) 通讯都用到 ...
- Linux I2C总线详解
概述: 1.I2C概念 2.I2C硬件结构图 3.I2C总线初始化 4.I2C控制器device 节点添加及driver注册 5.I2C设备节点添加及driver注册 5.adapter设备及驱动添加 ...
- SPI与I2C总线协议
目录: 一.SPI总线协议 1.什么是SPI 2.技术性能 3.接口定义与硬件连接 4.内部结构 5.传输时序 6.高速SPI 1)硬件电路 2)1MHz SPI传输问题 二.I2C总线协议 1. ...
最新文章
- qt获取窗口的右上角位置_如何获得 Qt窗口部件在主窗口中的位置--确定鼠标是否在某一控件上与在控件上的位置...
- Sizeof与Strlen的区别与联系(转)
- Android:禁用listView上的突出显示单击
- SAP-PM 的工具管理篇
- PO RELEASE 采购订单审核(支持多级审核)
- gnuradio android手机,如何搭配USRP在安卓设备上搭建GNU Radio
- CodeForces - 1373E Sum of Digits(贪心)
- 使用Matlab(R2018b)画复杂函数的图形(网格图meshgrid)及等高线contour
- Java面向对象编程篇6——注解与反射
- 源头防堵信息泄露 监管拟全面推行支付标记化
- memcached(十)动态扩容
- linux目录存 xml文件,将IDEA maven项目中src源代码下的xml等资源文件编译进classes文件夹...
- 生成解析器:Fsyacc
- 【工具向】分析FGUI依赖关系工具
- ubuntu给手机刷机安卓8.0 ROOT+Xposed+JustTrustMe+Kali NetHunter
- 螺旋分级机与水力分级机间的优缺点
- 关于长江的题目_高中优秀议论文题目【高中关于长江的作文题目加优秀范文】...
- js版【微信机器人】——wechat-robot
- 使用RocketMQ进行银行转账
- 【渝粤题库】国家开放大学2021春2114人体解剖生理学题目