51单片机(IIC协议OLED屏)

一、IIC协议

1、IIC协议概述

1.1、概述:IIC全称Inter-Integrated Circuit (集成电路总线) 是由PHILIPS公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备。IIC属于半双 工同步通信方式

1.2、特点:简单性和有效性。 由于接口直接在组件之上,因此IIC总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降 低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件

多主控(multimastering) 其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当 然,在任何时间点上只能有一个主控。

1.3、构成:IIC串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL,其时钟信号是由主控 器件产生。所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线 的SCL上。对于并联在一条总线上的每个IC都有唯一的地址。

 

2、时序分析

IIC总线在传输数据的过程中一共有三种类型信号,分别为:开始信号、结束信号和应答信号。

起始信号

 

void IIC_Start()
{
    scl = 0;
    sda = 1;
    scl = 1;
    _nop_();
    sda = 0;
    _nop_();
}

终止信号

 

void IIC_Stop()
{
    sda = 0;
    scl = 1;
    _nop_();
    sda = 1;
    _nop_();
}

应答信号

发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。 应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字 节; 应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功

 

char IIC_ACK()
{
    char flag;
    sda = 1;//就在时钟脉冲9期间释放数据线
    _nop_();
    scl = 1;
    _nop_();
    flag = sda;
    _nop_();
    scl = 0;
    _nop_();
    return flag;
}

数据发送

 

void IIC_Send_Byte(char dataSend)
{
    int i;
    for(i = 0;i<8;i++){
        scl = 0;//scl拉低,让sda做好数据准备
        sda = dataSend & 0x80;//1000 0000获得dataSend的最高位,给sda
        _nop_();//发送数据建立时间
        scl = 1;//scl拉高开始发送
        _nop_();//数据发送时间
        scl = 0;//发送完毕拉低
        _nop_();//
        dataSend = dataSend << 1;
}
}

二、oled屏

1、OLED写命令

写命令/数据的代码逻辑思路

1. start()

2. 写入 b0111 1000 0x78

3. ACK

4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据

5. ACK

6. 写入指令/数据

7. ACK

8. STOP

void Oled_Write_Cmd(char dataCmd)
{
// 1. start()
    IIC_Start();
// 2. 写入从机地址 b0111 1000 0x78
    IIC_Send_Byte(0x78);
// 3. ACK
    IIC_ACK();
// 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
    IIC_Send_Byte(0x00);
// 5. ACK
    IIC_ACK();
//6. 写入指令/数据
    IIC_Send_Byte(dataCmd);
//7. ACK
    IIC_ACK();
//8. STOP
    IIC_Stop();
}
void Oled_Write_Data(char dataData)
{
// 1. start()
    IIC_Start();
// 2. 写入从机地址 b0111 1000 0x78
    IIC_Send_Byte(0x78);
// 3. ACK
    IIC_ACK();
// 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
    IIC_Send_Byte(0x00);
// 5. ACK
    IIC_ACK();
///6. 写入指令/数据
    IIC_Send_Byte(dataData);
//7. ACK
    IIC_ACK();
//8. STOP
    IIC_Stop();
}

2、OLED的寻址模式

如何显示一个点?

有三种寻址模式,分别位页地址模式,水平地址模式和垂直地址模式,可以通过一下表格进行配置 内存管理

 

 页地址模式

 水平地址模式

 垂直地址模式

 

列地址选择

 如果写入0x08(b00001000)会显示什么呢 ?一个字节负责一个Page的一列显示

 三、代码实现

#include "reg52.h" 
#include "intrins.h"

sbit scl=P0^1;
sbit sda=P0^3;

void IIC_start()
{
	scl=0;//防止雪花
	sda=1;
	scl=1;
	_nop_();
	sda=0;
	_nop_();

}
void IIC_stop()
{
	scl=0;
	sda=0;
	scl=1;
	_nop_();
	sda=1;
	_nop_();

}

char IIC_ACK()
{
	char flag;
	sda=1;//就在时钟脉冲9期间释放数据线
  _nop_();
	scl=1;
	_nop_();
	flag=sda;
	_nop_();
	scl=0;
	_nop_();
	
	return flag;
}


void IIC_Send_Byte(char dataSend)
{
	int i;
	
	for(i=0;i<8;i++){
	  scl=0;//scl拉低做好数据准备
	  sda=dataSend & 0x80;  //1000 0000获得dataSend的最高位,给sda
	  _nop_();//发送数据建立时间
	  scl=1;//scl拉高开始传数据
	  _nop_();
	  scl=0;//发送完毕拉低
	  _nop_();
	  dataSend= dataSend << 1;
  }
}

void Oled_Write_Data(char dataData)
{
	//1.start
  IIC_start();
	//2.写入从机地址 0x78
	IIC_Send_Byte(0x78);
  //3.ACK
	IIC_ACK();
	//4.control byte: 0000 0000 写入命令  0100 0000 写入数据
	IIC_Send_Byte(0x40);
	//5.ACK
	IIC_ACK();
	//6.写入指令或数据
	IIC_Send_Byte(dataData);
	//7.ACK
	IIC_ACK();
	//8.STOP
	IIC_stop();
}

void Oled_Write_Cmd(char dataCmd)
{
	//1.start
  IIC_start();
	//2.写入从机地址 0x78
	IIC_Send_Byte(0x78);
  //3.ACK
	IIC_ACK();
	//4.control byte: 0000 0000 写入命令  0100 0000 写入数据
	IIC_Send_Byte(0x00);
	//5.ACK
	IIC_ACK();
	//6.写入指令或数据
	IIC_Send_Byte(dataCmd);
	//7.ACK
	IIC_ACK();
	//8.STOP
	IIC_stop();
}


void Oled_Init(void){
    Oled_Write_Cmd(0xAE);//--display off
    Oled_Write_Cmd(0x00);//---set low column address
    Oled_Write_Cmd(0x10);//---set high column address
    Oled_Write_Cmd(0x40);//--set start line address  
    Oled_Write_Cmd(0xB0);//--set page address
    Oled_Write_Cmd(0x81); // contract control
    Oled_Write_Cmd(0xFF);//--128   
    Oled_Write_Cmd(0xA1);//set segment remap 
    Oled_Write_Cmd(0xA6);//--normal / reverse
    Oled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
    Oled_Write_Cmd(0x3F);//--1/32 duty
    Oled_Write_Cmd(0xC8);//Com scan direction
    Oled_Write_Cmd(0xD3);//-set display offset
    Oled_Write_Cmd(0x00);//
     
    Oled_Write_Cmd(0xD5);//set osc division
    Oled_Write_Cmd(0x80);//
     
    Oled_Write_Cmd(0xD8);//set area color mode off
    Oled_Write_Cmd(0x05);//
     
    Oled_Write_Cmd(0xD9);//Set Pre-Charge Period
    Oled_Write_Cmd(0xF1);//
     
    Oled_Write_Cmd(0xDA);//set com pin configuartion
    Oled_Write_Cmd(0x12);//
     
    Oled_Write_Cmd(0xDB);//set Vcomh
    Oled_Write_Cmd(0x30);//
     
    Oled_Write_Cmd(0x8D);//set charge pump enable
    Oled_Write_Cmd(0x14);//
     
    Oled_Write_Cmd(0xAF);//--turn on oled panel     
}

void Oled_Clear()  //清屏函数
{
	int i;
	int j;
	
	for(i=0;i<8;i++){
   Oled_Write_Cmd(0xB0+ i);//page0--page7
	 //每个page从0列
	 Oled_Write_Cmd(0x00);
   Oled_Write_Cmd(0x10);
   //到127列,依次写入0,每写入数据,列地址自动偏移
	 for(j=0;j<128;j++){
   Oled_Write_Data(0); 
    }
  }
	
}

void Oled_Show_Image(unsigned char *image)//显示一张图  
{
	unsigned int i;
	unsigned int j;
	
	for(i=0;i<8;i++){
   Oled_Write_Cmd(0xB0+ i);//page0--page7
	 //每个page从0列
	 Oled_Write_Cmd(0x00);
   Oled_Write_Cmd(0x10);
   //到127列,依次写入0,每写入数据,列地址自动偏移
	 for(j=128*i;j<128 * (i+1);j++){
   Oled_Write_Data(image[j]);
    }
  }
	
}

void main()
{
	//1.OLED初始化
	Oled_Init();
	//2.选择一个位置
	//2.1确认页寻址模式
	Oled_Write_Cmd(0x20);
	Oled_Write_Cmd(0x02);
	Oled_Clear();//清屏函数
    //显示一条线
    Oled_Write_Data(0x08);
	Oled_Write_Data(0x08);
	Oled_Write_Data(0x08);
    Oled_Write_Data(0x08);
    Oled_Write_Data(0x08);
    Oled_Write_Data(0x08);
    Oled_Write_Data(0x08);
	while(1);//不让程序退出
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.kler.cn/a/5891.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【JavaEE】多线程之阻塞队列(BlockingQueue)

目录 1.了解阻塞队列 2.生产者消费者模型又是什么&#xff1f; 2.1生产者消费者模型的优点 2.1.1降低服务器与服务器之间耦合度 2.1.2“削峰填谷”平衡消费者和生产的处理能力 3.标准库中的阻塞队列&#xff08;BlockingQueue&#xff09; 3.1基于标准库&#xff08;Bloc…

树莓派Linux源码配置,树莓派Linux内核编译,树莓派Linux内核更换

目录 一 树莓派Linux的源码配置 ① 内核源码下载说明 ② 三种方法配置源码 二 树莓派Linux内核编译 ① 内核编译 ② 编译时报错及解决方案&#xff08;亲测&#xff09; 三 更换树莓派Linux内核 操作步骤说明 ● dmesg报错及解决方案&#xff08;亲测&#xff0…

链路上小段线的阻抗突变到底会不会影响信号质量?

一博高速先生成员&#xff1a;刘春 在进行PCB设计时&#xff0c;相信有经验的工程师都遇到过这种情况&#xff0c;在布线过程中&#xff0c;有时候由于电路结构或空间限制&#xff0c;需要中途某段走线变粗或变细&#xff0c;如串接电阻电容、下孔、BGA出线区域或走线密集区域…

【vscode】调试cocos creator

先看看 官方教程–使用 VS Code 调试网页版游戏 一、安装插件 Debugger for Chrome已弃用 安装 JavaScript Debugger (Nightly) 插件替代&#xff0c;其他步骤完全一样。 二、通过cocos creator打开任意js脚本&#xff0c;按F5&#xff0c;选择Web 应用&#xff08;Chrome&…

Python 文件读取

1、CSV 文件存储 1.1 写入 简单示例 import csvwith open(data.csv, a) as csvfile:writer csv.writer(csvfile) # 初始化写入对象&#xff0c;传入文件句柄writer.writerow([id, name, age]) # 调用 writerow() 方法传入每行的数据writer.writerow([1, rose, 1…

【Java】快速接入ChatGPT API实现聊天、生成图像

目录 申请API秘钥 发请求 发请求响应文本 发请求响应图像 申请API秘钥 访问https://platform.openai.com/ 登录后点击右上角的头像,如图&#xff1a; 获取到秘钥后接下来就开始搞代码啦~ 发请求 添加发请求和解析响应的maven依赖 <!-- https://mvnrepository.com/a…

dmesg 时间误差现象

1.案例现象 这天收到监控平台发来的告警&#xff0c;说有台机器程序崩溃了 因为以前也有过相关的错误&#xff0c;根据经验&#xff0c;用 dmesg命令看下内核信息 #-T 显示时间 dmesg -T | grep error [3月28 08:41] error info [3月30 09:55] error info发现有点不对劲&…

LAZADA数据平台API接入

Lazada成立于2012年&#xff0c;是东南亚本土领先的电子商务平台。 致力于通过商业和科技促进印尼、马来西亚、菲律宾、新加坡、泰国和越南六国市场发展。Lazada自2016年起成为阿里巴巴东南亚旗舰电商平台&#xff0c;获阿里巴巴集团前沿科技的支持&#xff0c;拥有东南亚全面…

GDB调试器

前言&#xff1a; GDB(GNU Debugger)是一个用来调试C/C程序的功能强大的调试器&#xff0c;是Linux系统开发 C/C最常用的调试器 程序员可以使用GDB来跟踪程序中的错误&#xff0c;从而减少程序员的工作量。 Linux 开发C/C 一定要熟悉 GDB VSCode是通过调用GDB调试器来实现C/C的…

我的谷歌书签

Form 表单 | Element Plusa Vue 3 based component library for designers and developershttps://element-plus.gitee.io/zh-CN/component/form.html#%E5%AF%B9%E9%BD%90%E6%96%B9%E5%BC%8F three.js exampleshttp://www.yanhuangxueyuan.com/threejs/examples/#software_geo…

HTTP协议发展历程-HTTP2【协议篇】

HTTP2.0 HTTP2为了解决HTTP1.1中存在的问题。其中慢启动和TCP连接竞争是TCP本身导致的&#xff0c;在H2中依赖的还是TCP协议&#xff0c;不过思路换了一下。 HTTP/2 的思路就是一个域名只使用一个 TCP 长连接来传输数据&#xff0c;这样整个页面资源的下载过程只需要一次慢启动…

C++中的重载运算符

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C &#x1f525;座右铭&#xff1a;“不要等到什么都没有了&#xff0c;才下…

【springBoot篇2】springBoot日志篇

目录 一、日志有什么作用 作用1&#xff1a;快速定位问题的所在之处(最主要) 作用2&#xff1a;记录用户的登录日志 作用3&#xff1a;记录系统的操作日志 作用4&#xff1a;记录方法的执行时间 二、日志怎样使用 ①先得到日志对象(slf4j的Logger对象) ​​​编辑 ②根…

C语言数据结构初阶(9)----树的概念及性质

CSDN的uu们&#xff0c;大家好。这里是C语言数据结构的第九讲。 目标&#xff1a;前路坎坷&#xff0c;披荆斩棘&#xff0c;扶摇直上。 博客主页&#xff1a; 姬如祎 收录专栏&#xff1a; 数据结构与算法 目录 1. 树的定义及相关概念 2. 树的表示方法 2.1 孩子兄弟表示法…

读书笔记|《高质量读研:教你如何写论文、做科研》 张军平

前言&#xff1a;去年封控期间在张老师的一次学术分享讲座上知道的这本书&#xff0c;原本以为这本书的内容就是老生常谈&#xff0c;就没有太在意。后来从学弟那里借到一本张老师撰写的《爱犯错的智能体》&#xff0c;读来觉得很有意思&#xff0c;于是乎找来这本书看&#xf…

GPT-5紧急叫停?千名专家联名呼吁,AI技术的未来又该何去何从?

在半个月前强势上线的GPT-4 &#xff0c;以其强大的性能再次掀起了一波关于人工智能技术的全民热潮。但GPT-4太强了&#xff0c;强到发指&#xff0c;不止群众恐慌&#xff0c;北京时间3月29日&#xff0c;全世界的 AI 大佬们纷纷出手&#xff0c;千名专家发表公开信&#xff0…

【动态绘图】python可视化--丝滑版

✅作者简介&#xff1a;在读博士&#xff0c;伪程序媛&#xff0c;人工智能领域学习者&#xff0c;深耕机器学习&#xff0c;交叉学科实践者&#xff0c;周更前沿文章解读&#xff0c;提供科研小工具&#xff0c;分享科研经验&#xff0c;欢迎交流&#xff01;&#x1f4cc;个人…

10秒去除WPS Office弹窗广告教程(2023.3.31最新)

目录 前言 步骤 1. 右击WPS Office&#xff0c;打开文件所在目录 2. 打开第二个文件夹 3. 进入office 6文件夹 4. 找到文件ksomisc.exe 5. 右击选择以管理员身份运行 6. 打开后是下面的界面&#xff0c;点击“高级(A)...” 7. 按照下图操作 8. 最后点击退出就设置完…

ThreeJS-纹理加载进度(十四)

使用纹理加载器对纹理加载进度进行监控 关键代码&#xff1a; //创建加载管理器 const manager new THREE.LoadingManager( () > { console.log("加载完成"); }, (url, loaded, total) > { console.log("当前正在加载资源" url); console.log(&qu…

LeetCode-583. 两个字符串的删除操作

目录题目思路动态规划一动态规划二题目来源 583. 两个字符串的删除操作 题目思路 两个字符串可以相互删了&#xff0c;而LeetCode-115. 不同的子序列只能删一个 动态规划一 1.确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j]&#xff1a;以i-1为结尾的…
最新文章