发新帖我要提问
12
返回列表
打印
[51单片机]

I2C通信———求大神看一下问题到底出在哪?

[复制链接]
楼主: 鼹鼠
手机看帖
扫描二维码
随时随地手机跟帖
21
鼹鼠|  楼主 | 2013-11-15 23:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
JasonWangSE 发表于 2013-11-15 19:18
除了12楼说的循环的问题外,我觉得有三点怀疑的地方:
1. I2CSend最后的SCL=1是否应改为SCL=0,否则第二次 ...

恩恩 你说的很对 其中我有个程序就是应为scl = 0,写成了scl = 1;这个中午已经改过来了 你说的那个sda = 1;是个应答位 我才刚开始学习这个 的确是可要可不要 但是这是为后面的学习铺垫 那个延时的知识点还不知道 非常感谢告知!!!不过这个程序已经调试出来了 问题已经解决!!!灰常感谢指点。。。

使用特权

评论回复
22
鼹鼠|  楼主 | 2013-11-15 23:48 | 只看该作者
ballack_linux 发表于 2013-11-15 23:05
好 待会我搭个仿真环境试试

#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
typedef unsigned char uint8;
sbit sda=P3^6;
sbit scl=P3^7;
void delay_ms(uint z)
{
        uint x,y;
        for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}
void delay()
{;;}
void init()
{
        scl=1;
        delay();
        sda=1;
        delay();
}
void start()
{
        sda=1;
        delay();
        scl=1;
        delay();
        sda=0;
        delay();
}
void stop()
{
        sda=0;
        delay();
        scl=1;
        delay();
        sda=1;
        delay();
}
void reply()
{
        uchar i=0;
        scl=1;
        delay();
        while((sda==1)&&(i<200))i++;
        scl=0;
        delay();
}
void unreply()
{
        sda=1;
        delay();
        scl=1;
        delay();
        scl=0;
        delay();
}                 
void write_byte(uchar dat)
{        
        uchar i;
        scl=0;
        delay();
        for(i=0;i<8;i++)
        {        
                if(dat&0x80)
                sda=1;
                else sda=0;
                dat<<=1;        
                 scl=1;
                delay();
                scl=0;
                delay();
        }
        //sda=1;
  scl = 1;
        delay();
}
uchar read_byte()
{
        uchar i,num;
       /* scl=0;
        delay();
        sda=1;
        delay();*/
        for(i=0;i<8;i++)
        {
                scl=1;
                delay();
                num<<=1;
                if(sda)
                {
                        num++;
                }                           
                scl=0;
                delay();               
        }
        return num;        
}

void UART_init(void)
{
SCON = 0X50;
TMOD &= 0X0F;
TMOD |= 0X20;
TH1 = 0XFD;
TL1 = 0XFD;
TR1 = 1;
}
void UART_send_byte(uint8 dat)
{
SBUF = dat;
while(!TI);
TI = 0;
}

void main()
{

UART_init();
        init();
        start();
        write_byte(0xa0);
        reply();
        write_byte(0xff);
        reply();
        write_byte(0xaa);
        reply();
        stop();
        delay_ms(10);
        start();
        write_byte(0xa0);
        reply();
        write_byte(0xff);
        reply();
        start();
        write_byte(0xa1);
        reply();
        
  UART_send_byte(read_byte());
        unreply();
        stop();
        while(1);
}
哈哈!!! 我把你那个程序修改了下 调试成功!!!发送回串口的终于是AA 了 而且按一下复位键只发送一个 但是还是有点不懂刚才那个程序为啥一次发送四个字节!!!你的结果咋样了???

11.jpg (60.2 KB )

11.jpg

使用特权

评论回复
23
鼹鼠|  楼主 | 2013-11-15 23:59 | 只看该作者
ballack_linux 发表于 2013-11-15 22:27
void UART_init(void)
{
SCON = 0X50;

那个十六进制前缀大小写都是一样 ,个人习惯,这个不影响程序运行。。。你说的那个uint dat 的问题我也意识到了

使用特权

评论回复
24
ballack_linux| | 2013-11-16 01:18 | 只看该作者
鼹鼠 发表于 2013-11-15 16:52
1.  我下载前几天写的uart通信程序 串口调试助手上和程序预期的效果一致。。。说明串口线没问题
2.  板子 ...

#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit sda=P2^0;
sbit scl=P2^1;
void delay_ms(uint z)
{
        uint x,y;
        for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}
void delay()
{;;}
void init()
{
        scl=1;
        delay();
        sda=1;
        delay();
}
void start()
{
        sda=1;
        delay();
        scl=1;
        delay();
        sda=0;
        delay();
}
void stop()
{
        sda=0;
        delay();
        scl=1;
        delay();
        sda=1;
        delay();
}
void reply()
{
        uchar i=0;
        scl=1;
        delay();
        while((sda==1)&&(i<200))i++;
        scl=0;
        delay();
}
void unreply()
{
        sda=1;
        delay();
        scl=1;
        delay();
        scl=0;
        delay();
}                 
void write_byte(uchar dat)
{       
        uchar i;
        scl=0;
        delay();
        for(i=0;i<8;i++)
        {       
                if(dat&0x80)
                sda=1;
                else sda=0;
                dat<<=1;       
                 scl=1;
                delay();
                scl=0;
                delay();
        }
        sda=1;
        delay();
}

uchar read_byte()
{
        uchar i,num;
        scl=0;
        delay();
        sda=1;
        delay();
        for(i=0;i<8;i++)
        {
                scl=1;
                delay();
                num<<=1;
                if(sda)
                {
                        num++;
                }                          
                scl=0;
                delay();               
        }
        return num;       
}

void sent_data(uchar a)
{       
        SBUF=a;
        while(!TI);
        TI=0;
}

void main()
{
        uchar c;
        TMOD=0x20;                 //“SBUF=b;”这条语句反馈给串口调试助手的也是对应
        TH1=0xfd;                 //的ASCII码,如果想串口调试助手显示所发的原数据,
        TL1=0xfd;                 //而不是ASCII码,则如果是字符,可加‘’,如果是
        TR1=1;                         //字符串,可加“”。
        SM0=0;
        SM1=1;
        REN=1;               

        init();
        start();
        write_byte(0xa0);
        reply();
        write_byte(255);
        reply();
        write_byte(0xaa);
        reply();
        stop();
        delay_ms(100);          

        start();
        write_byte(0xa0);
        reply();
        write_byte(255);
        reply();
        start();
        write_byte(0xa1);
        reply();
        c =read_byte();       
        sent_data(c);
        unreply();
        stop();               
        while(1);          
}

以上程序仿真测试中无任何问题,如下:

使用特权

评论回复
评分
参与人数 1威望 +2 收起 理由
鼹鼠 + 2 很给力!
25
ballack_linux| | 2013-11-16 01:44 | 只看该作者
鼹鼠 发表于 2013-11-15 23:48
#include
#include
#define uchar unsigned char

void write_byte(uchar dat)
最后的sda=1 你把它改成scl=1,没有任何意义
sda=1是为了释放总线,scl=1是啥作用?
I2C总线是SCL电平跳变的时候发送或接收数据的

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
鼹鼠 + 1 很给力!
26
鼹鼠|  楼主 | 2013-11-17 11:14 | 只看该作者
ballack_linux 发表于 2013-11-16 01:44
void write_byte(uchar dat)
最后的sda=1 你把它改成scl=1,没有任何意义
sda=1是为了释放总线,scl=1是 ...

恩恩。。。你说的很对!那个地方我将sda = 1;改成scl = 1;是因为只有scl = 1时数据才是稳定的 这个确实不影响

非常感谢!!!非常好奇你那个仿真环境是怎么搭建的 还有哪个电路图???求指教

使用特权

评论回复
27
ballack_linux| | 2013-11-17 12:14 | 只看该作者
鼹鼠 发表于 2013-11-17 11:14
恩恩。。。你说的很对!那个地方我将sda = 1;改成scl = 1;是因为只有scl = 1时数据才是稳定的 这个确实不 ...

呵呵  用Proteus啊  不过仿真不能尽信哦  有实物验证还是最好的

使用特权

评论回复
评分
参与人数 1威望 +2 收起 理由
鼹鼠 + 2
28
lhchen922| | 2013-11-17 19:54 | 只看该作者
示波器抓下图。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
鼹鼠 + 1
29
鼹鼠|  楼主 | 2013-11-17 20:21 | 只看该作者
lhchen922 发表于 2013-11-17 19:54
示波器抓下图。

这个 还不会用,正在学习中 不过程序已经调试出来了

使用特权

评论回复
30
lhchen922| | 2013-11-17 20:24 | 只看该作者
恩,加油,,要学会使用工具,,,
可以买个 Saleae逻辑分析仪,可以调试比如1wire、I2C、UART、SPI、CAN等。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
鼹鼠 + 1 赞一个!
31
鼹鼠|  楼主 | 2013-11-17 20:28 | 只看该作者
lhchen922 发表于 2013-11-17 20:24
恩,加油,,要学会使用工具,,,
可以买个 Saleae逻辑分析仪,可以调试比如1wire、I2C、UART、SPI、CAN等 ...

恩恩。。。我们学校的实验室有示波器,今天在淘宝上也看了一下逻辑分析仪 看学到后面用的频率高不 正打算入手买一个逻辑分析仪

使用特权

评论回复
32
GULANGGOGO| | 2013-11-18 08:44 | 只看该作者
受教了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则