📄 icc_m.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 + -