I^2C总线的SDA与CLK都是线与关系.
为了避免混乱I^2C总线要通过总线仲裁决定总线由哪一台主机控制
I^2C总线的数据位的有效性:时钟信号为高电平期间
数据线上的数据必须保持稳定,只有在时钟信号为低电平时,
数据线上的数据才可以变化.
图片
I^2C总线的起始信号与终止信号,每一字节必须是8位长度
发完还有一位应答位,所以一共会有9位.
在编写程序时,只要严格按照时序图来,万事OK,下面是我写的一示例程序,功能是先向2402芯片写入一字节数据,然后再将其读出,显示到数码管
#include
#define uint unsigned int
#define uchar unsigned char
sbit scl = P1^6;
sbit sda = P1^7;
uchar code table[]={0x7e,0x0c,0xb6,0x9e,0xcc,0xda,0xfa,0x0e,0xfe,0xde};
sbit sda0 = P1^0;
sbit clk = P1^1;
sbit dig1 = P1^2;
sbit dig2 = P1^3;
sbit dig3 = P1^4;
sbit dig4 = P1^ 5;
void delay(uint);
/** 初始化IIC,将i^2C总线的电平拉高 **/
void init()
{
sda = 1;
scl = 1;
delay(1);
}
/** 向IIC写入一个字节 **/
void write_byte(uchar b)
{
uchar i,temp;
temp = b;
scl = 0;
for(i=0;i<8;i++)
{
temp <<= 1;
sda = CY;
delay(1);
scl = 1;
delay(1);
scl = 0;
}
delay(1);
scl = 0;
sda = 1;
}
/** 从IIC读出一字节数据 **/
uchar read_byte()
{
uchar i,temp;
scl = 0;
sda = 1;
delay(1);
for(i=0;i<8;i++)
{
delay(1);
temp <<= 1;
scl = 1;
delay(1);
temp |= sda;
delay(1);
scl = 0;
}
delay(1);
scl = 0;
sda = 1;
return temp;
}
/** IIC的开始信号 **/
void start()
{
sda = 1;
delay(1);
scl = 1;
delay(1);
sda = 0;
delay(1);
sda = 1;
scl = 0;
}
/** IIC的停止信号 **/
void stop()
{
sda = 0;
delay(1);
scl = 1;
delay(1);
sda = 1;
scl = 0;
delay(1);
}
/** IIC的应答函数 **/
void response()
{
uchar temp = 0;
sda = 1;
scl = 0;
delay(1);
while(sda && temp<250)
temp ++;
scl = 1;
delay(1);
scl = 0;
delay(1);
sda = 1;
}
//延迟函数
void delay(uint u)
{
uint x,y;
for(x=u;x>0;x--)
for(y=110;y>0;y--);
}
/** 向数据码管写入一个字节数据 **/
void write(uchar u)
{
uchar i;
for(i=0;i<8;i++)
{
clk = 1;
sda0 = u&0x80;
clk = 0;
u = u<<1;
}
}
/** 显示一个3位的整数 **/
void display(uchar num)
{
uchar bai,shi,ge;
bai = num/100;
shi = num%100/10;
ge = num%10;
/* 显示个位 */
dig4 = 0;
write(table[ge]);
delay(10);
dig4 = 1;
/* 显示十位 */
dig3 = 0;
write(table[shi]);
delay(10);
dig3 = 1;
/* 显示百位 */
dig2 = 0;
write(table[bai]);
delay(10);
dig2 = 1;
}
/** 向2402芯片指定地址写入一字节数据 **/
void write2402(uchar add,uchar u)
{
start();
write_byte(0xa0);
response();
write_byte(add);
response();
write_byte(u);
response();
stop();
}
/** 从2402芯片指定地址读出一字节数据 **/
uchar read2402(uchar add)
{
uchar result;
start();
write_byte(0xa0);
response();
write_byte(add);
response();
start();
write_byte(0xa1);
response();
result = read_byte();
stop();
return result;
}
void main()
{
uchar result;
init();
write2402(5,159);
delay(20);
result = read2402(5);
while(1)
display(result);
}
关键字:51单片机 I^2C总线
引用地址:
51单片机之I^2C总线
推荐阅读最新更新时间:2024-03-16 15:21
基于51单片机的DDS函数信号发生器的设计
本文介绍基于51单片机的DDS函数信号发生器的设计。系统大致包括信号发生部分、数/模转换部分以及液晶显示部分三部分,通过程序设计方法产生锯齿波、正弦波、三角波、矩形波四种波形,通过按键来控制四种波形的类型选择、频率变化,并通过液晶屏1602显示其各自的类型以及频率值。 总体系统设计 该系统采用单片机作为数据处理及控制核心,由单片机完成人机界面、系统控制、信号的采集分析以及信号的处理和变换,采用按键输入,利用液晶显示电路输出数字显示的方案。将设计任务分解为按键电路、液晶显示电路等模块。下图为系统的总体框图 总体方框图 硬件实现及单元电路设计 振荡电路 单片机内部有一个高增益、反相放大器,其输入端为芯片引脚XTAL1,其输出端为
[测试测量]
51单片机的独立键盘
这几天打算好好开始看郭天祥的单片机视频,自己也写了一个独立键盘的51单片机程序,开发环境为Keil C51。 刚开始看,功能并不是很复杂,由51单片机的P1^7口接LED灯,P0口作为6位数码管的位选线和段选线,6位数码管每次显示相同的数字。位选和段选的控制由P2^7,P2^6口。按键只有一个,一端与地相连,一端接P3^7口。 当按下按键时,LED灯会发光,同时6位数码管显示的数字加1,从0~F后返回0。松开按键后,LED灯灭。 闲话少说,上代码: #include reg52.h #define uchar unsigned char sbit RDKey=P3^7; sbit LED=P1^7; s
[单片机]
51单片机数码管动态扫描驱动的设计
数码管由于发光亮度强,指示效果好,非常适合于电梯楼层等数值显示应用中。对于一位数码管,可以采用静态显示,但实际应用中都是需要显示多位数值,数码管模块也只能动态显示,因此笔者在这里简单分析一下数码管动态扫描驱动的实现。 1. 数码管原理概述 数码管由多个发光二极管封装在一起组成“8”字型的器件,引线已在内部连接完成,只引出它们的各个笔划,公共电极。数码管实际上是由七个发光管组成8字形构成的,加上小数点就是8个。这些段分别由字母a,b,c,d,e,f,g,dp来表示。数码管根据内部接法又可分成共阳极数码管和共阴极数码管。共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管(如下图SM*10501),共阴数
[单片机]
基于FPGA和8051单片机IP核的多功能频率计的设计与实现
频率是电信号中重要的物理量,在电子、通信系统中,信号的频率稳定度决定了整个系统的性能,准确测量信号的频率是系统设计的重要内容。 单片机广泛地应用于电子系统设计,其性价比高,大量的外围接口电路,使基于单片机的电子系统设计方便,周期缩短。然而,单片机的串行工作特点决定了它的低速性和程序跑飞,另外还存在抗干扰能力不强等缺点。EDA(Electronic Design Automation)技术以计算机为工具,在Quartus II软件平台上,对以硬件描述语言Verilog HDL/VHDL为系统逻辑描述手段完成的设计文件,自动地完成逻辑编译、化简、综合及优化、逻辑仿真,直至对特定目标芯片的适配、编译、逻辑映射和编程下载等工作,
[单片机]
学习51单片机必写的几个程序
51单片机偶完全自学的,因为想学的时候离学校开课还早得很。 学完了单片机,现在学校课也开完了,收获很大。现将偶学习经验写出来,供大家交流。 1、因为有了C语言和汇编语言的基础,加上模电学得不错。微机原理也上了。所以我只花了半天的时间把51的引脚功能和内部结构搞清楚了。偶认为学51重要的就是搞清内部结构和地址空间。 2、仅用了几个小时简单看了一下51的汇编指令和C语法。 我个人认为学习程序语言的语法规则是很简单的,且各种语言之间都有共通的地方,有了汇编和某种高级语言的基础学其它语言应该能很快上手。 3、直接编程练习,软件硬件实现。 我的第一个程序是跑马灯程序。 这个会让你熟悉端口的用法,普通流程控制。当然是C语言写一个,汇
[单片机]
42-基于51单片机的电子密码锁设计
具体实现功能 系统由AT89S52单片机+AT24C02数据存储模块+按键模块+LCD1602显示+报警模块等构成。 具体功能: 1、输入密码,且输入的密码显示在液晶显示屏上; 2、按下“DorBell”后,会响起门铃声; 3、初始密码为“1234”,输入正确后,显示“OK”,并且LED灯闪烁,表示开门; 4、输入密码错误后,显示“Eror”,三次输入错误后会报警; 5、按下“DELE”,清除输入的密码。 设计背景 电子密码锁在当前市场运用较为广泛,其主要通过对外接密码输入来实现对系统或电路的控制,并进一步控制系统机械开关的操作。相关电子产品通过系统编程控制能够以电子密码锁的形式来实现系统的开关,尤
[单片机]
51的单片机定时中断基本概念及简单实验
定时器相关内容 CPU时序的有关知识 ①振荡周期:为单片机提供定时信号的振荡源的周期(晶振周期或外加振荡周期)。 ②状态周期:2 个振荡周期为 1 个状态周期,用 S 表示。振荡周期又称 S 周期或时钟周期。 ③机器周期:1 个机器周期含 6 个状态周期,12 个振荡周期。 即机器周期=6个状态周期=12个震荡周期。 ④指令周期:完成 1 条指令所占用的全部时间,它以机器周期为单位。 外接晶振为 12MHz 时,51 单片机相关周期的具体值为: 振荡周期=1/12us; 状态周期=1/6us; 机器周期=1us; 指令周期=1~4us; 定时器/计数器 ①51 单片机有两组定时器/计数器,因为既可以定时,又可以计数,故称之为定时器
[单片机]
基于51单片机的EV动力蓄电池组电量计量系统
引言 随着汽车工业的迅速发展,解决汽车尾气排放所带来的大气污染问题的较好方案是发展无空气污染的交通工具,电动汽车随之应运而生。以蓄电池作为动力源的电动汽车,无论从技术上还是经济上都是最可行的。 电动汽车用的动力蓄电池通常由多节单体电池串联或者并联构成,一般串联的单体电池数可达到十至几十个,单体电池电压一般是12V,总电压在100V以上, 总容量在100Ah以上。本文所阐述的蓄电池性能检测系统在结构设计上可以根据需要增加或减少被检测电池的数量,具有较高的灵活性,单片机控制使精度可达 1%,利用改进的开路电压法进行数据运算,进一步提高了精度。 由于铅酸蓄电池容量有限并具有腐蚀性,镍镉蓄电池中镉是有污染的重金属,而镍氢电池的容量、充放电特
[单片机]