⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 icc_m.c

📁 上位机与Mega16通讯
💻 C
字号:
/**************************************************************************
        文件名:icc_m.c
		功  能;半双工 同步 串行通讯 主机例程
		        不采用中断
		  MCU :Mega16L
		晶  振:内部8MHz
		硬  件:主机        从机
		        PC0(SCL)--- PC0(SCL)
				PC1(SDA)--- PC1(SDA)
		说  明:从机地址0B00010000
		连 线:主机PORTA与LED相连
		运行说明:1)上位机通过串口向主机写(任意)一个字,以启动传输
		      主机首先向上位机回发来自上位机的数据
		      如果上位机向主机发送0x01,则主机从从机中读取数据,
		                   并向上位机发送读取的数据 
		      否则向从机中写入来自上位机的数据
		          2)主机向从机发送数据,每次发送后都点亮LED:
				    向从机写时,LED的亮暗与主机接收到的来自上位机的数据对应;
				    从从机读时,LED的亮暗与主机接收到的来自从机的数据对应。
	  已通过实验验证! 
**************************************************************************/
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/delay.h>
#include <avr/wdt.h>
#include <compat/twi.h>

#define uchar unsigned char
#define uint unsigned int
#define ulint unsigned long int
 
#define slave 0x10

#define read   0x01
#define write  0xfe

uchar l,rv;

void Initial_IO(void)
{DDRC=0x00;
 PORTC=(1<<PC0)|(1<<PC1);         //TWI两个端口带上拉电阻输入
 DDRA=0xff;                       //A口输出 
 PORTA=0xff;
}

void Initial(void)
{SREG&=0xEF;                      //关全局中断
 /*********串口设定***********/
 UBRRH=0x00;
 UBRRL=25;                        //波特率设定,19200bps 
 UCSRB=0x98;                      //RXCIE=1,开USART接收结束中断
                                  //RXEN=1,接受使能
                                  //TXEN=1,发送使能
                                  //8位数据长度   
 UCSRC=(1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1)|(1<<UPM1); //写UCSRC寄存器
                                  //偶校验位
                                  //1位停止位
                                  //8位数据长度
  /********看门狗设置*********/
 wdt_enable(WDTO_250MS);//看门狗定时器开启,定时时间1.0s
  /*******全局中断使能********/
 SREG=SREG|0x80;
}

/**************TWI主机操作***************/
//初始化TWI主机
void Initial_TWI_m(void)
{TWBR=200;
}

//发送START信号
uchar twi_start(void) 
{TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);//清上一步动作结束时置位的中断标志;
                                      //置位TWSTA,准备发送START:若总线空闲则发送START,
                                        //若总线忙则等待,直到检测到一个STOP,发送START
                                        //发送START,声明自己希望为主机;
										//发送START完毕后,必须软件清零START  
                                      //使能TWI操作与激活TWI接口
 while (!(TWCR & (1<<TWINT)));        //等待START发送完成
                                      //发送完成后TWINT置位,TWI数据传输被终止
 return TW_STATUS;                    //在TWINT清零前完成对TWSR的访问
}

//写1个字节
uchar twi_write(uchar c)
{TWDR=c;                              //将1个字节(地址+方向,或者数据)载入TWDR
 TWCR=(1<<TWINT)|(1<<TWEN);           //清上一步动作结束时置位的中断标志;
                                      //使能TWI操作与激活TWI接口,启动发送该字节
 while (!(TWCR & (1<<TWINT))) ;       //等待该字节发送完成
                                      //发送完成后TWINT置位,TWI数据传输被终止
 return TW_STATUS;                    //在TWINT清零前完成对TWSR的访问
}

//读1个字节,并根据ack给出相应应答: true时发ACK,false时发NACK
//uchar twi_read(uchar d,uchar ack)
uchar twi_read(uchar ack)
{uchar d,tmp=(1<<TWINT)|(1<<TWEN); //清上一步动作结束时置位的中断标志;
                                 //使能TWI操作与激活TWI接口,启动发送该字节
 if(ack)  tmp|=(1<<TWEA); 	     //返回应答ACK,表示接受到
                                 //需要返回ACK,则置位TWEA,如果发生以下情况,发出ACK脉冲:
                                 // 1)从机地址与主机发出的地址相符;
                                 // 2)TWGCE置位时接收到广播呼叫;
                                 // 3)接收到一个字节
 TWCR=tmp;                       //返回非应答NACK,表示下一步不需再发送了
                                 //需要返回NACK,不置位TWEA
 while (!(TWCR & (1<<TWINT))) ;  //等待接受字节,返回ACK/NACK
                                 //发送完成后TWINT置位,TWI数据传输被终止
 d=TWDR;                         //在TWINT清零前完成对TWDR的访问
 return d;                                
 // return TW_STATUS;              //在TWINT清零前完成对TWSR的访问
}

//发送STOP信号
void twi_stop(void)
{TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN);//清上一步动作结束时置位的中断标志;
                                  //置位TWSTO,TWI接口将在总线上产生STOP,然后TWSTO自动清零 
                                  //使能TWI操作与激活TWI接口
}
 
int main(void)
{Initial_IO();
 Initial();
 Initial_TWI_m();
 while(1)
 {wdt_reset();
  _delay_ms(100);
 } 
}

SIGNAL(SIG_UART_RECV)
{l=UDR;//读取接受的数据,清接受完成标志位RXC
 wdt_reset();
 while(!(UCSRA&(1<<UDRE)));UDR=l;
 if(l==0x01){
  twi_start();
  twi_write(slave|read);
  rv=twi_read(0);
  twi_stop();
  while(!(UCSRA&(1<<UDRE)));UDR=rv;
  while(1)
   {wdt_reset();
    PORTA=rv;
    _delay_ms(1000);
    SREG=SREG|0x80;
   }
  }
 else{
  twi_start();
  twi_write(slave&write);
  twi_write(l);
  twi_stop();
  while(1)
   {wdt_reset();
    PORTA=l;
    _delay_ms(1000);
    SREG=SREG|0x80;
   }
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -