» 您尚未 登录   注册 | 搜索 | 社区服务 | 帮助 | 无图版 | 左右分栏


AVR与虚拟仪器论坛 AVRVi.com -> AVR单片机论坛(主坛) -> 两个M16之间通过TWI进行通信的实验
 XML   RSS 2.0   WAP 

AVRVI的淘宝店 AVR单片机学习套餐 EasyAVR M128开发板 SK 国内最专业AVR开发工具商城

--> 本页主题: 两个M16之间通过TWI进行通信的实验 加为IE收藏 | 收藏主题 | 上一主题 | 下一主题
铜河



技术群用户 优秀斑竹奖

级别: 论坛版主
精华: 8
发帖: 580
威望: 1017 点
金钱: 6781 VI
贡献值: 253 点
技术积分: 34 点
在线时间:156(小时)
注册时间:1970-01-01
最后登录:2009-01-07
查看作者资料 发送短消息 推荐此帖 引用回复这个帖子

0 两个M16之间通过TWI进行通信的实验

近日,应网友的要求,做了两个M16通过TWI进行通信的实验,现将相关代码公布如下,欢迎各位朋友拍砖!
硬件联接:第一个M16实验板通过232与PC通信,设为主机。第二个M16学习板设为从机,从机地址在这里设为0x06(相当于24C02的0xA0),其SPI接口通过74HC595接四位LED数码管段选,PB0-PB3为数码管位选。两板间通过三条杜帮线将SCL、SDA、GND对应联接起来。其中SCL、SDA两管脚接4.7K上拉电阻。
实验方法:PC机上的串口调试助手按要求发送数据到主M16,主M16通过TWI传送到从M16,从M16将收到的数据在数码管上显示,同时将显示内容传回主M16并回送PC显示。
串口发送到主M16的控制命令为8字节,十六进制数据帧格式:第一字节0X55,帧头;第二字节0X06,从机地址;第三字节0X00,从机子地址(即从哪位数码管开始),范围为0-3;第四、五、六、七字节为数据,对应随后数码管的位显示,范围为0-9、A-F;第八字节0XAA,帧结束标志。
主机程序:
CODE:

/************************************
*   M16通过TWI向M16发送数据的程序   *
* 功   能:M16通过TWI读写M16     *
* 建立日期:2008年11月04日         *
* 设 计 者:铜河             *
* 版   本:V1.0             *
* 修改日期:2008年11月04日         *
* 主控芯片:ATmega16           *
* 时钟频率:外部晶体7.3728MHz     *
* 编 译 器:ICCAVR6.31A           *
************************************/
#include <iom16v.h>
#include <macros.h>

//-----------TWI状态定义-------------
//MT为主方式发送,MR为主方式接收
#define START           0x08     //启动TWI的响应
#define RE_START         0x10     //重新启动TWI的响应
#define MT_SLA_ACK         0x18     //发送地址已响应
#define MT_SLA_NOACK     0x20     //发送地址已非响应
#define MT_DATA_ACK         0x28     //发送数据已响应
#define MT_DATA_NOACK     0x30     //发送数据已非响应

#define MR_SLA_ACK         0x40     //主接收地址返应答
#define MR_SLA_NOACK     0x48     //主接收地址返非应答
#define MR_DATA_ACK         0x50     //主接收数据返应答
#define MR_DATA_NOACK     0x58     //主接收数据返非应答

//常用TWI主模式写和主模式读
#define Start()           (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))
#define STOP()           (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))
#define WAIT()           {while(!(TWCR&(1<<TWINT)));}   //等待操作完成
#define TESTACK()         (TWSR&0xF8)                 //读取状态数据
#define SETACK()         (TWCR|=(1<<TWEA))           //应答
#define SETNOACK()         (TWCR&=~(1<<TWEA))           //非应答
#define TWI()           (TWCR=(1<<TWINT)|(1<<TWEN))     //启动TWI读方式
#define WRITE8BIT(x)     {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}   //发送8位数据

unsigned char uart_buff[7]={0};     //串口接收缓冲
unsigned char xs[4];           //发送缓冲
unsigned char SLA_ADDR;           //需读写的从器件地址:从串口接收的数据中获取

/********************************
* 函数名称: void port_init(void)*
* 函数功能:端口初始化         *
********************************/
void port_init(void)
  {
  PORTA = 0xFF;
  DDRA = 0xFF;
  PORTB = 0x00;
  DDRB = 0xFF;
  PORTC = 0x00;
  DDRC = 0xFF;
  PORTD = 0x00;
  DDRD = 0x00;
  }

/************************************
* 函数名称: void delay_ms(uint i)   *
* 函数功能:延时函数           *
* 晶振频率:7.3728MHZ           *
* 实际延时:i mS             *
************************************/
void delay_ms(unsigned int i)
  {
  unsigned int a;
  for(;i;i--)
    {
    for(a=1055;a;a--)
        {;}
    }
  }

/************************************
* 函数名称: void timer1_init(void)   *
* 函数功能:定时器1初始化         *
* 预分频值:64                 *
* 工作方式:溢出中断           *
* 定时时间:500mSec             *
* 时钟频率:外部晶体 7.3728MHz     *
************************************/
void timer1_init(void)
  {
  TCCR1B = 0x00;
  TCNT1H = 0x1F;
  TCNT1L = 0x01;
  TCCR1A = 0x00;
  TCCR1B = 0x03;
  }

/************************************
*     定时器1溢出中断入口         *
************************************/
#pragma interrupt_handler timer1_ovf_isr:iv_TIMER1_OVF
void timer1_ovf_isr(void)
  {
  TCNT1H = 0x1F;
  TCNT1L = 0x01;
  PORTC ^= 1<<3;             //LED闪灯
  }

/************************************
* 函数名称: void twi_init(void)     *
* 函数功能:TWI 初始化           *
* 预分频值:1                 *
* 工作方式:主机方式 高速         *
* 时钟频率:外部晶体 7.3728MHz     *
************************************/
void twi_init(void)
  {
  TWCR = 0x44;
  }
 
/************************************
* 函数功能:将指定数据写入指定地址   *
* 入口参数:地址、数据           *
* 出口参数:操作成功1,不成功0     *
************************************/
unsigned char iic_write(unsigned char addr,unsigned char data)
  {
  unsigned char m;
  Start();                 //启动IIC
  WAIT();
  WRITE8BIT(SLA_ADDR);         //写从器件地址和写方式
  WAIT();
  WRITE8BIT(addr);           //写子地址
  WAIT();
  WRITE8BIT(data);           //写数据
  WAIT();
  STOP();                   //停止IIC
  delay_ms(10);             //延时等待
  return 0;
  }

/************************************
* 函数功能:从指定地址读取数据     *
* 入口参数:地址             *
* 出口参数:成功返回数据,不成功0   *
************************************/
unsigned char iic_read(unsigned char addr)
  {
  unsigned char temp,m;
  Start();                 //启动IIC
  WAIT();
  WRITE8BIT(SLA_ADDR);         //写从器件地址和写方式
  WAIT();
  if(TESTACK()!=MT_SLA_ACK)return 0;
  WRITE8BIT(addr);           //写子地址
  WAIT();
  if(TESTACK()!=MT_DATA_ACK)return 0;
  Start();                 //IIC重新启动
  WAIT();
  if(TESTACK()!=RE_START)return 0;
  WRITE8BIT(SLA_ADDR+1);         //写从器件地址和读方式
  WAIT();
  if(TESTACK()!=MR_SLA_ACK)return 0;//应答
  TWI();                   //启动主IIC读方式
  WAIT();
  if(TESTACK()!=MR_DATA_NOACK)return 0;//非应答
  temp = TWDR;             //读取接收到的数据
  STOP();                   //停止IIC
  return temp;
  }

/************************************
* 函数名称: void uart0_init(void)   *
* 函数功能:串口UART0初始化         *
* 波 特 率:9600,8,n,1           *
* 时钟频率:外部晶体 7.3728MHz     *
************************************/
void uart0_init(void)
  {
  UCSRB = 0x00;
  UCSRA = 0x00;
  UCSRC = BIT(URSEL) | 0x06;
  UBRRL = 0x2F;
  UBRRH = 0x00;
  UCSRB = 0x98;
  }

/****************************************
* 函数名称: void Uart_Transmit(uchar i)   *
* 函数功能:串口字节数据发送函数     *
* 工作方式:查询方式             *
* 晶振频率:7.3728MHZ,波特率9600     *
****************************************/
void Uart_Transmit(unsigned char i)
  {
  UDR = i;                   //发送数据
  while (!(UCSRA & (1<<UDRE)));     //等待发送缓冲器为空
  }

/***************************************
*       串口接收中断函数       *
***************************************/
#pragma interrupt_handler uart0_rx_isr:12
void uart0_rx_isr(void)             //串口接收中断函数
  {
  unsigned char temp;             //变量
  static unsigned char count;         //接收位置计数

  temp = UDR;

  switch (count)
    {
    case 0x00:                 //启动字节校对,如果对则开始接收数据
        if (uart_buff[6] == 0x99)   //判断主程序是否处理完前面的数据
          {
          return ;
          }
        if (temp == 0x55)         //启动字节判定
          {
          PORTC |= 1<<7;
          uart_buff[0] = temp;   //提取第一个字节
          count ++;           //计数值增加
          }
        break;
    case 0x01:
        SLA_ADDR = temp;
        count ++;
        break;
    case 0x02:
        uart_buff[1] = temp;
        count ++;
        break;
    case 0x03:
        uart_buff[2] = temp;
        count ++;
        break;
    case 0x04:
        uart_buff[3] = temp;
        count ++;
        break;
    case 0x05:
        uart_buff[4] = temp;
        count ++;
        break;
    case 0x06:
        uart_buff[5] = temp;
        count ++;
        break;
    case 0x07:
        if (temp == 0xAA)         //数据校验
          {
          uart_buff[6] = 0x99;   //接收正确,设置标志,等待处理
          }
        PORTC &=~(1<<7);
        count = 0x00;           //接收完,计数变量清除
        break;
    default :                 //计数位置异常捕获
        count = 0x00;
        PORTC &=~(1<<7);
        break;
    }
  }

/************************************
* 函数名称: void init_devices(void)   *
* 函数功能:器件初始化           *
************************************/
void init_devices(void)
  {
  CLI();
  port_init();
  timer1_init();
  twi_init();
  uart0_init();

  MCUCR = 0x00;
  GICR = 0x00;
  TIMSK = 0x04;
  SEI();
  }

/***************************
*       主函数       *
***************************/
void main(void)
  {
  unsigned char m;
 
  init_devices();
 
  while(1)
    {
    if(uart_buff[6]==0x99)         //收到新的串口数据
        {
        PORTC ^= 1<<5;
        for(m=0;m<4;m++)         //通过TWI发送4个显示数据
          {
          iic_write((uart_buff[1]+m),uart_buff[m+2]);
          }
        uart_buff[6]=0;           //处理完毕,串口可接收新数据
        delay_ms(50);
       
        for(m=0;m<4;m++)
          {
          xs[m] = iic_read(m);   //读取从机数据
          Uart_Transmit(xs[m]);   //通过串口发回
          }
        }    
    }
  }

从机程序:
/************************************
*     学习板接收TWI显示程序     *
* 功   能:用TWI接收主机数据显示   *
* 建立日期:2008年11月04日         *
* 设 计 者:铜河             *
* 版   本:V1.0             *
* 修改日期:2008年11月04日         *
* 主控芯片:ATmega16           *
* 时钟频率:外部晶体7.3728MHz     *
* 编 译 器:ICCAVR6.31A           *
************************************/
#include <iom16v.h>
#include <macros.h>

volatile unsigned char IIC_STATE;     //IIC通信状态机

//-----------TWI状态定义-------------
//从机编程设计的几个状态机
#define STATE_IIC_ADDR     0xC3
#define STATE_IIC_WDATA     0xA5
#define STATE_IIC_RDATA     0x5A
#define STATE_IIC_STOP     0

volatile unsigned char     IIC_ADDR;
volatile unsigned char     IIC_DATA;   //当前数据

#define SLA_Device_Addr     0x06     //定义器件地址

//从机方式中断响应状态码
#define SR_SLA_ACK         0x60     //从机接收地址响应
#define SR_ALL_ACK         0x70     //从机接收广播响应
#define SR_DATA_ACK         0x80     //从机接收数据响应
#define SR_DATA_NOACK     0x88     //从机接收数据非应答
#define SR_ALL_DATA_ACK     0x90     //从机接收广播数据应答
#define SR_ALL_DATA_NOACK   0x98     //从机接收广播数据非应答
#define SR_STOP_RESTART     0xA0
#define ST_SLA_ACK         0xA8     //从机发送地址应答
#define ST_DATA_ACK         0xB8     //从机发送数据应答
#define ST_DATA_NOACK     0xC0     //从机发送数据非应答
#define ST_LAST_DATA_ACK   0xC8

//从机各种操作
#define TWI_STATE()         (TWSR&0xF8)   //读取状态数据
#define SLA_AUTOACK()     (TWCR=(1<<TWEA)|(1<<TWINT)|(1<<TWEN)|(1<<TWIE))   //自动产生应答
#define SLA_SEND8BIT(x)     {TWDR=(x);TWCR=(1<<TWEA)|(1<<TWINT)|(1<<TWEN)|(1<<TWIE);}   //发送8位数据
#define SLA_RESUME()     (TWCR=(1<<TWEA)|(1<<TWINT)|(1<<TWEN)|(1<<TWIE))   //恢复等待状态

//定义全局变量
unsigned char s[4];           //定义显示缓冲数组:S0为个位、S3为千位
unsigned char i;

//定义显示代码:0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,暗
unsigned char disp[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
                0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};


//---------端口初始化----------
void port_init(void)
  {
  PORTB = 0xFF;
  DDRB = 0xFF;
  PORTC = 0x00;
  DDRC = 0xFF;
  PORTD = 0x00;
  DDRD = 0xFF;
  }

/************************************
*   SPI初始化函数:主模式,1/4fck   *
************************************/
void SPI_Init(void)
  {
  DDRB |= (1<<PB3)|(1<<PB5);     //设置MOSI和SCK为输出,其他为输入
  SPCR = (1<<SPE)|(1<<MSTR);     //使能SPI主机模式,设置时钟速率为fck/4
  }

/************************************
*         SPI数据发送函数         *
************************************/
void SPI_T(unsigned char i)
  {
  SPDR = i;                 //启动数据传输
  while (!(SPSR & (1<<SPIF)))     //等待传输结束
    {
    ;
    }
  }

/************************************
*     通过595向数码管输出数据     *
* 入   口:data 待显示的数据     *
*         i 数据显示的位         *
************************************/
void SPI_595_Out(unsigned char data,unsigned char i)
  {
  PORTB &= ~(1<<4);           //准备锁存
  PORTB |= 0x0F;             //先关位码
  SPI_T(data);             //再送数据
  PORTB |= 1<<4;             //锁存数据
  PORTB &= ~(0x08>>i);         //最后开位码
  }

/************************************
*       定时器0中断函数组         *
* 溢出中断:预分频256           *
* 功   能:扫描显示           *
* 定时时长:4MS (7.3728MHz)         *
* 实际时长:4.000mSec (误差0.0%)   *
* 设 计 者:tonghe             *
************************************/
//------------初始化函数---------------
void timer0_init(void)
  {
  TCCR0 = 0x00;             //先关闭定时器0
  TCNT0 = 0x8D;           //装载初值
  TCCR0 = 0x04;           //启动定时器0
  }

//--------定时器0中断向量入口----------
#pragma interrupt_handler timer0_ovf_isr:10
void timer0_ovf_isr(void)
  {
  TCNT0 = 0x8D;             //重装初值
  i++;
  if(i>3)i=0;
  SPI_595_Out(disp[s[i]],i);   //送显数据
  }

//---------TWI初始化----------
void twi_init(void)
  {
  TWAR = SLA_Device_Addr;
  TWCR = 0x45;
  }
 
//----------TWI中断入口----------
#pragma interrupt_handler twi_isr:iv_TWI
void twi_isr(void)
  {
  unsigned char nc;
  nc = TWI_STATE();
  switch(nc)
    {
    case SR_SLA_ACK:           //从地址匹配,写传输,ACK已返回
        IIC_STATE = STATE_IIC_ADDR;   //下一步接收数据的地址
        SLA_AUTOACK();
        break;
    case SR_DATA_ACK:           //接收主机送来的从机数据地址或数据,ACK已返回
        if(IIC_STATE==STATE_IIC_ADDR)//如果是地址
          {
          IIC_ADDR = TWDR;
          IIC_STATE = STATE_IIC_WDATA;//下一步接收数据
          }
        else
          {
          IIC_DATA = TWDR;         //是数据
          s[IIC_ADDR] = IIC_DATA;     //将数据存入显示缓冲
          }
        SLA_AUTOACK();
        break;
    case ST_SLA_ACK:             //从地址匹配读数据
    case ST_DATA_ACK:             //TWDR里数据已发送,接收到ACK
        IIC_STATE = STATE_IIC_RDATA;
        SLA_SEND8BIT(s[IIC_ADDR++]);   //发送数据
        break;
    case ST_DATA_NOACK:             //TWDR里数据已发送,接收到NOACK
        IIC_STATE = STATE_IIC_STOP;
        SLA_AUTOACK();
        break;
    case SR_STOP_RESTART:           //主机写命令结束或读命令重新开始
        SLA_AUTOACK();
        break;
    default:                   //从机模式转到未被寻址状态
        SLA_RESUME();
        break;
    }
  }

//------------器件初始化----------
void init_devices(void)
  {
  CLI();
  port_init();
  timer0_init();

  twi_init();
  SPI_Init();

  MCUCR = 0x00;
  GICR = 0x00;
  TIMSK = 0x05;
  SEI();
  }

//------------主函数------------
void main(void)
  {
  init_devices();
 
  while(1);
  }


学习开发利器:AVRmega128开发板,AVR仿真器,AVR编程器,AVR核心板四合一,仅需498元
[楼 主] | Posted: 11-05 09:48 顶端
admin

终身成就奖 金点子奖 原创先锋奖 技术群用户
头衔:先行者先行者

级别: 管理员
精华: 74
发帖: 4224
威望: 4338 点
金钱: 89645 VI
贡献值: 80 点
技术积分: 73 点
在线时间:2428(小时)
注册时间:1970-01-01
最后登录:2009-01-07
查看作者资料 发送短消息 推荐此帖 引用回复这个帖子



精华,谢谢。 辛苦了

发代码的时候 将代码部分用
CODE:
[ code ][ /code ] 注意无空格
括起来,就不会出现将[ i ]解析成斜体的问题了

学习开发利器:AVRmega128开发板,AVR仿真器,AVR编程器,AVR核心板四合一,仅需498元

AVRVi 与您共同发展! 赠人玫瑰,手留余香。
一份好的资料,放在机器中会成为垃圾文件;
如果共享出来,就能有成千上万的朋友受益;
每人贡献一点,中国的电子技术将迅速提高。
[1 楼] | Posted: 11-05 10:14 顶端
zhaojun_xf



级别: 圣骑士
精华: 1
发帖: 74
威望: 77 点
金钱: 1179 VI
贡献值: 0 点
技术积分: 3 点
在线时间:62(小时)
注册时间:2008-04-17
最后登录:2009-01-01
查看作者资料 发送短消息 推荐此帖 引用回复这个帖子



学习----
学习开发利器:AVRmega128开发板,AVR仿真器,AVR编程器,AVR核心板四合一,仅需498元
[2 楼] | Posted: 11-13 07:46 顶端
vincent_qiu





级别: 新手上路
精华: 0
发帖: 2
威望: 3 点
金钱: 20 VI
贡献值: 0 点
技术积分: 0 点
在线时间:6(小时)
注册时间:2008-12-09
最后登录:2009-01-03
查看作者资料 发送短消息 推荐此帖 引用回复这个帖子



嗨,,,哥们,,,你的“#pragma interrupt_handler twi_isr:iv_TWI”这个地方的iv_TWI应该怎么理解呢??想不明白,,,应该写成18吧??

还有哦,,搞TWI能不能软仿呢??有没有特别的软件呢??

学习开发利器:AVRmega128开发板,AVR仿真器,AVR编程器,AVR核心板四合一,仅需498元
[3 楼] | Posted: 12-21 22:02 顶端
junyuansun





级别: 新手上路
精华: 0
发帖: 5
威望: 6 点
金钱: 49 VI
贡献值: 0 点
技术积分: 0 点
在线时间:0(小时)
注册时间:2008-02-15
最后登录:2008-12-22
查看作者资料 发送短消息 推荐此帖 引用回复这个帖子



hao,hao,hao,hao,hao
学习开发利器:AVRmega128开发板,AVR仿真器,AVR编程器,AVR核心板四合一,仅需498元
[4 楼] | Posted: 12-22 13:31 顶端
hilltang





级别: 新手上路
精华: 0
发帖: 1
威望: 2 点
金钱: 10 VI
贡献值: 0 点
技术积分: 0 点
在线时间:0(小时)
注册时间:2008-08-26
最后登录:2008-12-22
查看作者资料 发送短消息 推荐此帖 引用回复这个帖子



给个电路图就好了,我这新手不会画啊,唉
学习开发利器:AVRmega128开发板,AVR仿真器,AVR编程器,AVR核心板四合一,仅需498元
[5 楼] | Posted: 12-22 14:03 顶端
铜河



技术群用户 优秀斑竹奖

级别: 论坛版主
精华: 8
发帖: 580
威望: 1017 点
金钱: 6781 VI
贡献值: 253 点
技术积分: 34 点
在线时间:156(小时)
注册时间:1970-01-01
最后登录:2009-01-07
查看作者资料 发送短消息 推荐此帖 引用回复这个帖子



QUOTE:
引用第3楼vincent_qiu12-21 22:02发表的:
嗨,,,哥们,,,你的“#pragma interrupt_handler twi_isr:iv_TWI”这个地方的iv_TWI应该怎么理解呢??想不明白,,,应该写成18吧??

还有哦,,搞TWI能不能软仿呢??有没有特别的软件呢??

1、中断号用iv_TWI这个在相应芯片的头文件中有定义,这样写的目的是具有通用性,因为不同的芯片其相同功能的中断号也许不同,但宏定义一般是相同的,程序移植到其它芯片时可不用修改这里。
2、不知能不能软仿,没试过。

学习开发利器:AVRmega128开发板,AVR仿真器,AVR编程器,AVR核心板四合一,仅需498元
[6 楼] | Posted: 12-25 19:54 顶端
vincent_qiu





级别: 新手上路
精华: 0
发帖: 2
威望: 3 点
金钱: 20 VI
贡献值: 0 点
技术积分: 0 点
在线时间:6(小时)
注册时间:2008-12-09
最后登录:2009-01-03
查看作者资料 发送短消息 推荐此帖 引用回复这个帖子



哥们,,,还有个问题啊,,,我现在怎么试也没试成功,,,我用了两张板子,都是M16,,一张是8M的晶振,一张是16M的晶振,,这样的话,,在设置方面有什么要求吗??

下面是我写的程序,,主机是一直写,,从机只是接收数据,,然后在数码管上显示数字,,,但怎么样都没有显示出来,,,不知道要怎么办,,你帮我看看哪里出错了。。

//主机程序
#include<iom16v.h>
#include<macros.h>

#define uchar unsigned char
#define uint unsigned int

#define START 0X08
#define MT_SLA_ACK 0X18
#define MT_DATA_ACK 0X28

#define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(TWEN))
#define Stop() (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))
#define Wait() while(!(TWCR&(1<<TWINT)))
#define TestACK() (TWSR&0XF8)
#define SetACK() (TWCR|=(1<<TWEA))
#define Writebyte(twi_d) {TWDR=(twi_d);TWCR=(1<<TWINT)|(1<<TWEN);}

void twi_init()
{
  TWBR=0X20;
  TWSR=0;
  TWCR=0X44;
}

uchar writeB(uchar devadd,uchar data)
{
  Start();
   if(TestACK()!=START)
   {
    return 0;
   }
   Writebyte(devadd);
   Wait();
   if(TestACK()!=MT_SLA_ACK)
   {
    return 0;
   }
   Writebyte(data);
   Wait();
   if(TestACK()!=MT_DATA_ACK)
   {
    return 0;
   }
   Stop();
   return 1;  
}

void main()
{
  twi_init();
   while(1)
   {
      writeB(0x06,123);
   }
}




//从机程序

#include<iom16v.h>
#include<macros.h>

#define uchar unsigned char
#define uint unsigned int

#include "SMG.c"   //显示程序

#define SR_SLA_ACK 0X60
#define SR_DATA_ACK 0X80

#define TWI_STATE() (TWSR&0XF8)
#define SLA_AUTOACK() (TWCR=(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE))

uchar shu;
void twi_init()
{
TWAR=0X06;
TWCR=0X45;
}

#pragma interrupt_handler twi_isr:18  

void twi_isr()   //我连是否有进入中断都不知道哩...
{
uchar nc;
nc=TWI_STATE();
switch(nc)
{
  case SR_SLA_ACK:
   case SR_DATA_ACK:
      shu=TWDR;
        SLA_AUTOACK();
        break;
   default:
      break;
}
}

void init_devices(void)
{
CLI();
twi_init();
SREG|=BIT(7);
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x05;
SEI();
}

void main()
{
init_devices();
init_io();
while(1)
{
    show(shu);
}

}

学习开发利器:AVRmega128开发板,AVR仿真器,AVR编程器,AVR核心板四合一,仅需498元
[7 楼] | Posted: 12-30 01:07 顶端

AVR与虚拟仪器论坛 AVRVi.com -> AVR单片机论坛(主坛)