A. 单片机任意引脚都可以做IIC接口吗
可以的,51单片机使用引脚模拟iic时序,所以对引脚没限制
B. 两个51单片机如何通过i2c通讯
一般情况下,要进行I2C通讯,你最起码其中有一个芯片要本身就带有I2C通讯接口,用这个带有I2C接口的芯片来作从器件,这样就相对好处理一点。你要是两个都不带这个接口,来模拟的话,很有难度。除非你对I2C协议很清楚,不过从楼主的提问来看,估计就不怎么熟悉这种协议。
所以建议还是用别的通讯方式吧,比如用SPI,相对会好处理一点,用其中一个芯片的INTx来模拟CS接口,作为从器件在中断中来处理,另外一个就模拟主器件来控制从器件,这样或许会好弄点。如果楼主确实需要通讯,还是赶快换个思路吧,要是卡在一个地方动不了,会耽误你的进程的,祝你好运!
C. 51单片机如何模拟I2C总线中从机接收ID,发送数据的程序
#include /*头文件的包含*/
#include
#define uchar unsigned char /*宏定义*/
#define uint unsigned int
/*端口位定义*/
sbit BELL_OUT=P3^5;
sbit SCL="P1"^3;/*模拟I2C数据传送位*/
sbit SDA="P1"^4;/*模拟I2C时钟控制位*/
bit ack; /*应答标志位*/
/*********************************************************************
起动总线函数
函数原型: void Start_I2c();
功能:启动I2C总线,即发送I2C起始条件
********************************************************************/
void Start_I2c()
{
SDA="1"; /*发送起始条件的数据信号*/
_nop_();
SCL="1"; /*起始条件建立时间大于4.7us,延时*/
_nop_();
SDA="0"; /*发送起始信号*/
_nop_(); /* 起始条件锁定时间大于4μs*/
SCL="0"; /*钳住I2C总线,准备发送或接收数据 */
_nop_();
}
/***********************************************
结束总线函数
函数原型: void Stop_I2c();
功能:结束I2C总线,即发送I2C结束条件
***********************************************/
void Stop_I2c()
{
SDA="0"; /*发送结束条件的数据信号*/
_nop_(); /*发送结束条件的时钟信号*/
SCL="1"; /*结束条件建立时间大于4μs*/
_nop_();
SDA="1"; /*发送I2C总线结束信号*/
_nop_();
}
/*******************************************************************
字节数据传送函数
函数原型: void SendByte(uchar c);
功能:将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状
态位进行操作(不应答或非应答都使ack=0 假) 。发送数据正常,ack=1;
ack=0表示被控器无应答或损坏。
********************************************************************/
void SendByte(uchar c)
{
uchar BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) /*要传送的数据长度为8位*/
{
SCL="0";
if((c<
else SDA="0";
SCL="1"; /*置时钟线为高,通知被控器开始接收数据位*/
_nop_(); /*保证时钟高电平周期大于4μs*/
}
//从机应答,可以用应答和非应答信号代替
_nop_();
SCL="0";
_nop_();
SDA="1"; //
_nop_();
SCL="1";
_nop_();
if(SDA==1){ack=0;} /*判断是否接收到应答信号*/
else ack="1";
SCL="0";
_nop_();
}
/*******************************************************************
字节数据传送函数
函数原型: uchar RcvByte();
功能:用来接收从器件传来的数据,并判断总线错误(不发应答信号),
发完后请用应答函数。
********************************************************************/
uchar RcvByte()
{
uchar retc;
uchar BitCnt;
retc="0";
for(BitCnt=0;BitCnt<8;BitCnt++)
{
SCL="1"; /*置时钟线为高使数据线上数据有效*/
_nop_();
retc="retc"<<1;
if(SDA==1) retc="retc"+1; /*读数据位,接收的数据位放入retc中 */
SCL="0";
}
return(retc);
}
/********************************************************************
应答子函数
原型: void Ack_I2c();
功能:主控器进行应答信号
********************************************************************/
void Ack_I2c()
{
SDA="0"; /*在此发出应答信号 */
_nop_();
SCL="0";
_nop_();
SCL="1";
_nop_();
SCL="0"; /*清时钟线,钳住I2C总线以便继续接收*/
_nop_();
SDA="1";
_nop_();
}
/********************************************************************
非应答子函数
原型: void NoAck_I2c();
功能:主控器进行非应答信号
********************************************************************/
void NoAck_I2c()
{
SDA="1"; /*在此发出非应答信号 */
_nop_();
SCL="1";
_nop_();
SCL="0"; /*清时钟线,钳住I2C总线以便继续接收*/
}
/*******************************************************************
向无子地址器件发送字节数据函数
函数原型: bit ISendByte(uchar sla,ucahr c);
功能:从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla。如果
返回1表示操作成功,否则操作有误。
********************************************************************/
bit ISendByte(uchar sla,uchar c)
{
Start_I2c(); /*启动总线*/
SendByte(sla); /*发送器件地址*/
if(ack==0)return(0);
SendByte(c); /*发送数据*/
if(ack==0)return(0);
Stop_I2c(); /*结束总线*/
return(1);
}
/*******************************************************************
向有子地址器件发送多字节数据函数
函数原型: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);
功能:从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件地址sla,
子地址suba,发送内容是s指向的内容,发送no个字节。如果返回1表示
操作成功,否则操作有误。
********************************************************************/
bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no)
{
uchar i;
Start_I2c(); /*启动总线*/
SendByte(sla); /*发送器件地址*/
if(ack==0)return(0);
SendByte(suba); /*发送器件子地址*/
if(ack==0)return(0);
for(i=0;i
{
SendByte(*s); /*发送数据*/
if(ack==0)return(0);
s++;
}
Stop_I2c(); /*结束总线*/
//delayMs(1); //
return(1);
}
/*******************************************************************
向无子地址器件读字节数据函数
函数原型: bit IRcvByte(uchar sla,ucahr *c);
功能:从启动总线到发送地址,读数据,结束总线的全过程,从器件地址sla,返
回值在c。如果返回1表示操作成功,否则操作有误。
********************************************************************/
bit IRcvByte(uchar sla,uchar *c)
{
Start_I2c(); /*启动总线*/
SendByte(sla+1); /*发送器件地址*/
if(ack==0)return(0);
*c=RcvByte(); /*读取数据*/
NoAck_I2c(); /*发送非就答位*/
Stop_I2c(); /*结束总线*/
return(1);
}
/**********************************************************************
向有子地址器件读取多字节数据函数
函数原型: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);
功能:从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件地址sla,
子地址suba,读出的内容放入s指向的存储区,读no个字节。如果返回1
表示操作成功,否则操作有误。
**********************************************************************/
bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no)
{
Start_I2c(); /*启动总线*/
SendByte(sla); /*发送器件地址*/
if(ack==0)return(0);
SendByte(suba); /*发送器件子地址*/
if(ack==0)return(0);
Start_I2c();
SendByte(sla+1);
if(ack==0)return(0);
while(no!=1)
{
*s=RcvByte();/*发送数据*/
Ack_I2c(); /*发送就答位*/
s++;
no--;
}
*s=RcvByte();
NoAck_I2c(); /*发送非应位*/
Stop_I2c(); /*结束总线*/
return(1);
}
D. 求教:两个51单片机之间的IIC通讯
IIC通讯只能是TTL连接通信,要求两个单片机是近距离的,应在1米以内。既然是TTL连接,为何不用串口呢,也是TTL连接,串口通信简单多了。
而IIC通信,两个单片机都是用引脚来模拟的,通信协议比较麻烦,写程序很麻烦的,又何苦呢?
E. 51单片机iic总线有哪些io口
IO口模拟其实就是数据口配合时钟口一位一位地接受或发送数据,然后存到内存里。
单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。
相当于一个微型的计算机,和计算机相比,单片机只缺少了I/O设备。概括的讲:一块芯片就成了一台计算机。它的体积小、质量轻、价格便宜、为学习、应用和开发提供了便利条件。同时,学习使用单片机是了解计算机原理与结构的最佳选择。
单片机的使用领域已十分广泛,如智能仪表、实时工控、通讯设备、导航系统、家用电器等。
运算器有两个功能:
(1)执行各种算术运算。
(2)执行各种逻辑运算,并进行逻辑测试,如零值测试或两个值的比较。
运算器所执行全部操作都是由控制器发出的控制信号来指挥的,并且,一个算术操作产生一个运算结果,一个逻辑操作产生一个判决。
F. 单片机的几种传输方式的总结
学习了51单片机以及STM32后总结下单片机与外设或者上位机通讯的几种传输方式
串口、COM口是指的物理接口形式(硬件)。而TTL、RS-232、RS-485是指的电平标准(电信号)
串行通信:指数据一位一位顺序传送
串行接口:简称串口(COM口)
并行通信:一组数据的各数据位在多线上同时被传输
并行接口:一种接口,各数据位同时被传输,传输速度快,效率高,一般用于MCU
串行通信分为:
单工:数据单项传送
半双工:数据能双向传送但不能同时
全双工:数据能同时双向传送
通用的、及支持同步也支持异步的接收、发送“模块”,在芯片内部,与SPI、I2C一起构成单片机的总线“枝干”,对于串口,串口通信指串口按位(bit)发送和接收字节,尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。
串行通信技术标准EIA-232/485也就是以前所称的RS-232/485。
232是PC机与通信工业中应用最广泛的一种串行接口,RS232单端通信,传输距离可达15米,最高速率20Kbps。
RS485传输速率为10Mbps,最大传输距离1219米,,采用二线制时可实现真正的多点双向通信,而采
用四线连接时只能实现点对多点通信,无论四线还是二线连接方式总线上可接多达 32 个设备。
串行通信传输速率用于说明传输的快慢。在串行通信中,数据是按位进
行传送的,因此传输速率用每秒钟传送格式位的数目来表示,称之波特率
(band rate)。每秒传送一个格式位就是 1 波特。常用的波特率有:4800、
9600、19200、115200 波特。
串口三个脚:TX、RX、GND
IIC总线是一种两线式串行总线,支持多主控,其中任何能够进行发送和接收的设备都可以成为主总线,一个主控能够控制信号的传输和时钟频率,当然在任何时间点上只能有一个主控。IIC总线是由数据线SDA和时钟SCl构成的串行总线,可发送和接收数据,在CPU与被控IC之间,IC与IC之间进行双向传送,最高传送速率100Kbps,各种被控制电路均并联在这条总线上,每个设备模块都有唯一的地址,IIC总线上的每一个设备模块既是主控器或被控器,又是发送器或接收器,这取决于你要实现的功能是怎样的。
CPU发出的控制信号分为地址码和控制量两部分
IIC总线传输过程中有三种信号:起始信号,终止信号,应答信号。
起始信号:SCL 为高电平时,SDA 由高电平向低电平跳变,开始传送数据;
终止信号:SCL 为低电平时,SDA 由低电平向高电平跳变,结束传送数据;
应答信号:接收数据的 IC 在接收到 8bit 数据后,向发送数据的 IC 发出
特定的低电平脉冲,表示已收到数据。CPU 向受控单元发出一个信号后,
等待受控单元发出一个应答信号,CPU 接收到应答信号后,根据实际情
况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单
元出现故障。
SPI允许单片机和外围设备或者单片机之间高速同步数据传输,SPI可以有主机和从机模式之选,通信的主从机之间通过移位寄存器同时交换数据。目前自己用的以主机模式居多。SPI需要四线:SS,MISO,MOSI,SCK。
通信过程:在设置好SPI的工作模式:包括SCK频率(数据传输速率),工作速度,主从模式,以及数据接收发送对应的时钟极性。在主模式下,将SS拉低表示通信的开始,然后通过向SPI数据寄存器中写入一字节的数据后自动启动时钟SCK开始进行一次通信,通信完成后会产生相应的中断标志,标志一个字节数据的传送完成。通信完成后将SS脚拉高,表示通信过程已经结束。
注意SS引脚的设置:当设置为从机模式时,SS引脚应设置为输入,拉低的时候SPI才能起作用,拉高的话是消极的SPI模式;在主机模式下,SS引脚可以设置,一般应设置为输出,如果设置为输入的话应保持为高,否则将不能进行正常的主机模式操作。
单片机通讯方式
G. 51单片机I2C总线问题,郭天祥51的188页,有3个问题不懂,第一,这个write是个啥,为啥用
bit和uchar 之类的差不多,只不过uchar=8位, bit=1位而已。都是变量,编译器在编译过程中分配地址。除非你指定,否则这个地址是随机的。这个地址是整个可寻址空间,RAM+FLASH+
扩展空间。
bit只有0和1两种值。uchar有256种值。
code是存储在单片机的flash里面,不是存在内存里面了。所以一般固定意义的数据,比如数码管的段码,一个图片的数据信息,都是用code定义,让这些数据放在flash里面,节省内存空间。因为51单片机的RAM很少,只有128(或者256)字节,要是定义的数据(而且是在使用时不做改变的)太多,RAM肯存不下。所以定义code,放在flash里面。要知道52单片机的flash有8K字节!远比256字节的RAM多。
H. 什么51单片机型号支持iic
大部分51单片机都不支持iic,好象只有C8051F410系列支持,估计这个芯片不便宜
一般都用普通IO引脚来模拟iic总线时序