码迷,mamicode.com
首页 > 其他好文 > 详细

九齐MCU io口模拟I2C

时间:2020-06-13 23:41:16      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:main   输出   border   ack   art   朋友   要求   ddr   data   

IO口模拟I2C的要点:

  1. 数据帧符合标准的I2C协议
  2. 分的清楚ACK与NACK的区别,是那个设备下拉。
  3. 数据位时间符合要求

项目合作开发,吹牛扯蛋、交朋友 ,请联系:18665321219

技术图片

#include "iic_p.h"
#include <ny8.h>
#include "main.h"
#include <ny8_constant.h>
#include <stdint.h>


#define sda_out()  IOSTA=(IOSTA & ((uint8_t)(~ C_PA6_Input)))  //输出
#define sda_in()   IOSTA=(IOSTA | C_PA6_Input)  //输入

#define sda   PORTAbits.PA6   //sda输出高 
#define scl   PORTAbits.PA4   //scl输出高,写程序注意默认让其保持高电平

void delayus(uint8_t tim) 
{
     while(tim--)    //2.4us周期 clk_8M
     {
         NOP();
         NOP();
         NOP();
         NOP();
        
         NOP();
         NOP();
         NOP();
         NOP();
     }
}

void i2c_stop(void)
{
     scl = 0;
     delayus(1);
     sda = 0;
     sda_out();
     delayus(2);
     scl = 1;
     delayus(1);
     sda = 1;
}

void i2c_start(void)
{
     sda = 1;    //
     delayus(1);
     scl = 1;    //发送停止位后将SCL及SDA置位
     delayus(1);
     sda = 0;
     delayus(1);
}

//测试ok
void trandata(uint8_t data)
{
     //IOSTB=(IOSTB & ((uint8_t)(~ C_PB2_Input)));  //输出
     uint8_t i;
    
     //scl = 0;
     for( i = 0;i<8;i++ )
     {
         scl = 0;
         delayus(1);
         if((data & 0x80) == 0x80)
         {
             sda = 1;
         }
         else
         {
             sda = 0;
         }
         data <<=1;
         delayus(2);
         scl = 1;
         delayus(3);
     }
     //scl = 0;
     //delayus(3);
     //sda = 0;   //因该把IO输出禁止,不然slaver无法下拉
}

//测试ok
void revdata(uint8_t *data)
{
     uint8_t i;
     //sda_in();
    
     for(i=0;i<8;i++)
     {
         scl = 0;
         delayus(3);
         scl = 1;
         delayus(1);
         *data <<= 1;
         if(sda==1)
         {
             *data |= 0x01;    //首位置为一
         }
         else
         {
             *data &= 0xfe;
         } 
         delayus(2);
     }
}

//测试ok
void i2c_nack(void)
{
     scl = 0;
     delayus(1);
     sda = 1;
     sda_out();
     delayus(2);
     scl = 1;
     delayus(3);
}


//测试ok
uint8_t i2c_dectack(void)
{
     uint8_t ackflg;
    
     scl = 0;
     delayus(1);
     sda_in();
     delayus(2);
     scl = 1;
     delayus(1);
    
     if(sda ==1)
     {
        ackflg = 0;  //为接收到应答
     }
     else
     {
        ackflg = 1;  //接收到应答
     }
     delayus(2);
     return ackflg;
}

//测试ok   3ms
uint8_t i2c_wtdata(uint8_t address,uint8_t data)
{
     uint8_t temp,errflg=0;
     i2c_start();
     temp = 0xa0;      //地址位赋值1010add(R/W)
    
     trandata(temp);
     if(i2c_dectack() == 0)
     {
         errflg = 1;    //未接收到应答数据
     }
     scl = 0;
     delayus(1);
     sda = 1;
     sda_out();
    
     temp = address;
     trandata(temp);
     if(i2c_dectack() == 0)
     {
         errflg = 1;    //未接收到应答数据
     }
     scl = 0;
     delayus(1);
     sda = 1;
     sda_out();
    
     trandata(data);
     if(i2c_dectack() == 0)
     {
         errflg = 1;    //未接收到应答数据
     }
  // scl = 0;
  // delayus(3);
  // sda = 0;
  // sda_out();
    
     i2c_stop();
     return errflg;
}

//测试ok //测试不稳定
uint8_t curddata(uint8_t *data)
{
      uint8_t temp,errflg=0;
      i2c_start();
      temp = 0xa1;   //地址位赋值1010add(R/W)
    
      trandata(temp);
      if(i2c_dectack() == 0)
      {
          errflg = 1;    //未接收到应答数据
      }
     
      //sda_out();
      revdata(data);
      i2c_nack();
     
      i2c_stop();
      return errflg;
}

//测试ok  4ms
uint8_t i2c_rddata(uint8_t address,uint8_t *pdata)
{
      uint8_t temp,errflg=0;
     
      i2c_start();
      temp = 0xa0;   //地址位赋值1010000(R/W)
    
      trandata(temp);
      if(i2c_dectack() == 0)
      {
          errflg = 1;   //未接收到应答数据
      }
      scl = 0;
      delayus(1);
      sda = 1;          //默认为上拉
      sda_out();
     
      temp = address;
      trandata(temp);
      if(i2c_dectack() == 0)
      {
         errflg = 1;    //未接收到应答数据
      }
      scl = 0;
      delayus(1);
      sda = 1;
      sda_out();
     
      if(curddata(pdata) == 1)
      {
          errflg = 1;
      }
      return errflg;
}

/*
//写数据遵守写入读出
void i2cbus_wt(uint8_t address,uint8_t data)
{
     uint8_t temp;
    
     do
     {
         while(i2c_wtdata(address,data) == 1);  //写入数据
         while(curddata(&temp) == 1);  //读出数据
        
     } while(data != temp);  //比较通过视为写入成功
}
*/

九齐MCU io口模拟I2C

标签:main   输出   border   ack   art   朋友   要求   ddr   data   

原文地址:https://www.cnblogs.com/logicexpression/p/13121966.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!