打印
[PIC®/AVR®/dsPIC®产品]

pic12f1822 IO模拟 I2C通信

[复制链接]
3506|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jie6511|  楼主 | 2014-9-12 11:19 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
我要通过i2c写入eeprom数据控制灯的开关,器件地址0x34,从地址0x07,目标数据0xfe(开灯),目前碰到的问题是main函数里面发送数据,目前程序里面我是直接写入(器件地址,从地址,数据),但是灯无响应。请大大们帮我看看是哪里出错了
#include "pic12f1822.h"
#include "pic.h"
//#include "I2C.h"
#define uchar unsigned char  //定义无符号字符类型
#define uint unsigned int    //定义无符号字符类型

void i2c_start(void);                         //I2C打开
void i2c_stop(void);                        //I2C关闭
void send_byte(uchar c);                        //发送单个字节
void senddata(uchar ad_main,uchar ad_sub,uchar c);

#define ack 1                 //主应答
#define no_ack 0        //从应答

#define sda RA1                        //IIC数据脚
#define scl RA0                        //IIC时钟脚

//内部RC振荡器,看门狗关,上电延时开,外部复位关,代码保护关,数据保护关,低电复位关,时钟输出关,时钟内外切换关,时钟监视器关,闪存读写关,倍频锁相环关,堆栈使能关,低电压烧录使能开
__CONFIG(FOSC_INTOSC&WDTE_OFF&PWRTE_ON&MCLRE_OFF&CP_OFF&CPD_OFF&BOREN_OFF&CLKOUTEN_OFF&IESO_OFF&FCMEN_OFF&WRT_OFF&PLLEN_OFF&STVREN_OFF&LVP_ON);
void delay1ms(uint k)
{        uchar i,j;
        for(i=0;i<k;i++)
                {j=100;
                 while(j--);
                }
}
void init()
{       
        //FOSC频率
        OSCCON=0b01101010;        // 4MHZ内部振荡器,指令周期1us
        ANSELA=0;               
        //PORTA端口设置
        TRISA=0b00100000;        //RXD为输入,其余为输出
        PORTA=0b00100000;       
        APFCON=0b10000100;                //RA5、TA4配置有RX/TX功能
}

void i2c_start(void)
{        TRISA1=0;
        sda = 1;//发送起始条件的数据信号
        NOP();//1us
        scl = 1;
        NOP();//起始条件建立时间大于4.7us,延时
        NOP();
        NOP();
        NOP();
        NOP();
        sda = 0;//发送起始信号
        NOP();//起始条件锁定时间大于4us
        NOP();
        NOP();
        NOP();
        NOP();
        scl = 0;//嵌住I2C总线准备发送或接收数据
        NOP();
}

void i2c_stop(void)
{        TRISA1=0;
        sda = 0;//发送结束条件的数据信号
        NOP();
        scl = 1;//发送结束条件的时钟信号
        NOP();//结束条件建立时间大于4us
        NOP();
        NOP();
        NOP();
        NOP();
        sda = 1;//发送I2C总线结束信号
        NOP();NOP();NOP();NOP();NOP();
        scl=0;NOP();NOP();scl=1;
}

void send_byte(uchar c)
{
        uchar i;
        TRISA1=0;
        for(i=0;i<8;i++)
        {
                scl=0;
                if((c<<i) & 0x80)
                        sda=1; //判断发送位
                else
                        sda=0;
                NOP();
                scl=1;
                NOP();
                scl=0;
        }
        NOP();
        sda=1;                 //发送完8bit,释放总线准备接收应答位
        NOP();
        scl=1;
        NOP();        //sda上数据即是从应答位
        scl=0;                //不考虑从应答位但要控制好时序
        NOP();
}

void i2c_ack_main(uchar ack_main)
{        TRISA1=1;
        scl=0;
        if(ack_main)sda=0;//ack主应答
        else
        sda=1;//no_ack无需应答
        NOP();
        NOP();
        scl = 1;
        NOP();//时钟低电平周期大于4us
        NOP();NOP();
        NOP();NOP();
        scl = 0;//清时钟线,嵌住I2C总线以便接收
        NOP();
}

uchar read_byte(void)
{
        uchar i;
        uchar c;
        c=0;
        scl=0;
        NOP();
        TRISA1=1;  //sda总线 IO配置输入
        sda=1; //置数据线为输入方式
        for(i=0;i<8;i++)
        {
        NOP();
        scl=0; //置时钟线为低,准备接收数据位
        NOP();
        sda=1; //置时钟线为高,使数据线上数据有效
        NOP();
        c<<=1;
        if(sda)
        c+=1; //读数据位,将接收的数据存c
        }
        scl=0;
        return c;
}

void senddata(uchar ad_main,uchar ad_sub,uchar c)
{       
        i2c_start();
        send_byte(ad_main); //发送器件地址
        NOP();
        send_byte(ad_sub); //发送器件子地址
        NOP();
        send_byte(c); //发送数据s
        NOP();
        i2c_stop();
}

void readdata(uchar ad_main,uchar ad_sub,uchar s)
{
        uchar i;
        uchar *sdata;       
        i2c_start();
        send_byte(ad_main);
        send_byte(ad_sub);
        send_byte(ad_main+1);
        for(i=0;i<8;i++)
        {        TRISA1=1;
                *sdata=read_byte();
                i2c_ack_main(ack); //主应答<ack=1>
                sdata++;
        }
        s=read_byte();
        i2c_ack_main(no_ack); //无需应答<no_ack=0>
        i2c_stop();
}

void main()
{       
        init();
        delay1ms(255);//延时255ms
        senddata(0x34,0x07,0xfe);//写入器件地址0x34,从地址0x07,数据0xfe
        while(1);
        delay1ms(100);       
}
沙发
wangch_sh| | 2014-9-12 18:20 | 只看该作者
好好检查时序

使用特权

评论回复
板凳
hsst| | 2014-9-13 16:20 | 只看该作者
应答方面的时序可能有问题

使用特权

评论回复
地板
jingchengye| | 2014-9-16 10:37 | 只看该作者
为什么我在用MPLAB X编译的时候,使用NOP();就报错了呢?

~3(@Y}{~[%UZHLW1SWM$$XQ.png (4.92 KB )

~3(@Y}{~[%UZHLW1SWM$$XQ.png

使用特权

评论回复
5
zhimagod| | 2014-9-23 08:14 | 只看该作者
1822貌似有硬件IIC的吧,MPLAB X里面用那个配置插件的话使用硬件IIC更方便的

使用特权

评论回复
6
yehen0611| | 2015-8-5 10:49 | 只看该作者
学习学习

使用特权

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

本版积分规则

1

主题

1

帖子

1

粉丝