打印
[AVR单片机]

怎么在MEGA128上编写模拟IIC啊

[复制链接]
2939|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Karlshen|  楼主 | 2009-12-11 23:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这里有个模拟IIC程序,可是最后用示波器观测,得不到我想要的IIC。有高手知道一下吗?
#include <iom128v.h>
#include <macros.h>
#define SDAI DDRC&=0xfd
#define SDAO DDRC|=0x02
#define SDAR PINC&0x02
#define SDA1 PORTC|=0x02
#define SDA0 PORTC&=0xfd
#define SCL1 PORTC|=0x01
#define SCL0 PORTC&=0xfe
#define SCLO DDRC|=0X01
unsigned char SystemError,AskFlag;
void io_init(void) {

   DDRA = 0x00;                                       
   PORTA = 0xFF;                                       
   DDRB = 0x00;                           
   PORTB = 0xFF;                    
   DDRC = 0xFF;                                    
   PORTC = 0xFF;
   DDRD = 0x00;
   PORTD = 0xFF;
   DDRE = 0x00;
   PORTE = 0xFF;
   DDRF = 0x00;
   PORTF = 0xFF;
   DDRG = 0x00;
   PORTG = 0xFF;
}
void delay(unsigned char n)
{
    unsigned char i;
    for(i=0;i<n;i++) ;
}
// 函数名称: iic_start()
// 函数功能: 启动I2C总线子程序
void iic_start(void)
{     
    SDAO;
      SCLO;
    SDA1;
    delay(10);
      SCL1;
    delay(15);
    SDA0;
    delay(10);
    SCL0;
}
/*===================================================================================*/
// 函数名称: iic_stop()
// 函数功能: 停止I2C总线数据传送子程序
void iic_stop(void)
{     
    SDAO;
      SCLO;
    SDA0;/*SDA=0*/
    delay(10);
    SCL1;/*SCL=1*/
    delay(15);
    SDA1;/*SDA=1*/
    delay(10);
    SCL0;
}

/*====================================================================================*/
// 函数名称: iic_check
// 函数功能: 主机应答位检查子程序,迫使数据传输过程结束
void iic_check(void)
{     
    SDAI;
      SCLO;
    delay(80);
    SCL1;
    AskFlag = 0;
    if(SDAR)
    {
        AskFlag = 1; // 若SDA=1表明非应答,置位非应答标志AskFlag
    }
    SCL0;
}
/*====================================================================================*/
// 函数名称: iic_putc
// 入口参数: ch
// 函数功能: 发送一个字节
void iic_putc(unsigned char pChar)
{
    unsigned char i=8;
      SCLO;
    SDAO;
    SCL0;
    while(i--)
    {
    if(pChar&0x80)
    {
        SDA1;
    }
    else
    {
        SDA0;
    }
    delay(10);
    SCL1;
    pChar<<=1;
    delay(20);
    SCL0;
}
}
/*===================================================================================*/
// 函数名称: iic_getc
// 返回接收的数据
// 函数功能: 接收一字节子程序
unsigned char iic_getc(void)
{
    unsigned char i=8,pChar=0;
      SCLO;
    SDAI;
    SCL0;
    while(i--)
    {
        SCL1;
        delay(5);
        pChar<<=1;
        if(SDAR)
        {
              pChar++;
        }
        delay(10);
        SCL0;
        delay(20);
    }
    return(pChar);
}
  void main (void)
    {
    io_init();
    while(1)
    {
      iic_start();
        iic_putc(0xf2);
        iic_stop();
        }
        }

相关帖子

沙发
commp| | 2009-12-12 00:20 | 只看该作者
我做过,关键是数据线的方向寄存器,老要变来变去,没有准双向的好用
用示波器观察IO的波形看错在哪里,这样比较方便找到问题。别忘了先写IIC的器件地址。

使用特权

评论回复
评分
参与人数 2威望 +2 收起 理由
suoma + 1
lovelyegle + 1
板凳
lovelyegle| | 2009-12-12 22:20 | 只看该作者
楼上的回答很好,学习了!

使用特权

评论回复
地板
suoma| | 2009-12-12 22:49 | 只看该作者
学习

使用特权

评论回复
5
huamunv| | 2009-12-14 20:51 | 只看该作者
顶一个

使用特权

评论回复
6
双龙| | 2009-12-16 16:25 | 只看该作者
MEGA128 自带 I2C

使用特权

评论回复
7
commp| | 2009-12-16 20:33 | 只看该作者
我用AVR也是IO口模拟,自带的I2C用起来比较麻烦

使用特权

评论回复
8
Karlshen|  楼主 | 2009-12-29 22:33 | 只看该作者
谢谢各位

使用特权

评论回复
9
tcy65| | 2010-1-25 10:29 | 只看该作者
登记一下,以后再来看。

使用特权

评论回复
10
大碗拉面| | 2010-1-25 13:29 | 只看该作者
其实AVR的硬件IIC模块挺好用的。我在Mega32上用过,控制EEPROM
现把驱动代码给你,希望有所帮助

void I2C_init(void)
{
  TWSR = 0x00;           //TWI状态寄存器初始化
  TWAR = 0x00;           //本机从机地址为0H
  //TWBR = 0x08;           //速率为100K
  TWBR = 0x20;
  TWCR = 0x44;           //允许ack应答,使能TWI
}
/***************************
产生启动信号
****************************/
unsigned char I2C_Start(void)
{
  unsigned char count = 0;
  TWCR = (1 << TWINT)|(1 << TWSTA)|(1 << TWEN);
  while( (!(TWCR & (1 << TWINT)))&&(count < 200) )
  {
      count++;
  }
  if( (TWSR & 0xf8) != TW_START )
     return I2C_ERR;
  else
      return I2C_OK;
}
/************************
产生停止信号
************************/
void I2C_Stop(void)
{
   TWCR = (1 << TWINT)|(1 << TWEN)|(1 << TWSTO);
}
/******************************
向总线写1字节,并返回有无应答
*******************************/
unsigned char I2C_Write(unsigned char data)
{
  unsigned char count = 0;
  TWDR = data;
  TWCR = (1 << TWINT)|(1 << TWEN);
   while( (!(TWCR & (1 << TWINT)))&&(count < 200) )
  {
       count++;
  }
  if( (TWSR & 0xf8) != TW_MT_SLA_ACK )
      return I2C_ERR;
  else
      return I2C_OK;
}
/********************************
读1字节,
ack = 1时,应答。
ack = 0时,不应答
********************************/
unsigned char I2C_Read(unsigned char ack)
{
  unsigned char count = 0;
  if(ack)
    TWCR = (1 << TWINT)|(1 << TWEN)|(1 << TWEA);   
  else
    TWCR = (1 << TWINT)|(1 << TWEN);               
  while( (!(TWCR & (1 << TWINT)))&&(count < 200) )
  {
     count++;
  }
   return TWDR;                  
}

使用特权

评论回复
11
laslison| | 2010-1-26 12:02 | 只看该作者
学习

使用特权

评论回复
12
大江名誉| | 2010-1-28 14:25 | 只看该作者
本帖最后由 大江名誉 于 2010-1-28 14:36 编辑

我做过,关键是数据线的方向寄存器,老要变来变去,没有准双向的好用
-------------------------------------------------------------------------------
其实并不麻烦,把 PORTx 寄存器对应位设为0,加个上拉电阻,只设方向寄存器DDRX就可以了。
例如以B口的 1:SDA,2:SCL为例:
#define    SDA1    DDRB &= ~(1<<1)       //设 SDA 为 1
#define    SDA0    DDRB |=    (1<<1)       //设 SDA 为 0
#define    SDA      (PINB & (1<<1))          //读  SDA

#define    SCL1    DDRB &= ~(1<<2)       //设 SCL 为 1
#define    SCL0    DDRB |=    (1<<2)       //设 SCL 为 0
#define    SCL      (PINB & (1<<2))          //读  SCL

楼主的你外部引脚有加外部上拉电阻吗?加个5k的就可以了。

使用特权

评论回复
13
大江名誉| | 2010-1-28 14:39 | 只看该作者
DDRC = 0xFF;                                    
   PORTC = 0xFF;
---------------------

DDRC = 0xfc;                                    
   PORTC = 0xFc;
试下。

使用特权

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

本版积分规则

81

主题

734

帖子

1

粉丝