专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

AVR单片机串口操作程序

作者:善良死神   来源:互联网   点击数:  更新时间:2014年06月05日   【字体:

 #include

#include
#include
#include
#include
 
 
#define FOSC 8000000 //mcu工作时钟频率
 
 
typedef unsigned int uint16;
typedef unsigned char uchar8;
 
 
uchar8 DoubleIRData[25]={0x64,0x00,0x20,0x04,0x40,0x00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //双红外发射数据 取PD2作为驱动远程红外发射
//uchar8 SingleIRData[25]={0x60,0x00,0x04,0x00,0x04,0x00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} //取PD2作为驱动远程红外发射 //取PD3驱动红外发射
 
 
uchar8 BitCount=0; //载波计数
uchar8 BetyCount=0; //位计数
volatile uchar8 UsartDataBuff=0;
volatile uchar8 ChargeFlag=0,LED_Count;
volatile uchar8 SYSCount=0;
volatile uint16 ADCCurrent1=0; //AD0转换结果  电压检测
volatile uint16 ADCCurrent3=0; //AD3结果转换 电流检测
 
 
void Port_Init(void)
{
DDRA  = 0b00000000;     //AD采样 PA0 PA1
PORTA = 0b00000000;     //PA口:初始化0
//PB PC 没有使用
DDRD  = 0b11111110;     //PD2 为远程红外发射 PD3 和 PD4 状态指示灯,P3未充电 P4表示充电 PD5和PD6 双红外近区发射 PD7 开关充电使能
PORTD = 0b00000011;     //初始化输出为0 其中USART 接收口上拉高电平 等待接收中断
 
 
}
 
 
void ADC_Init(void)
{
ADCSRA=0x00; //ADC控制状态寄存器
ADMUX =0x40; //ADC 多工选择寄存器 参考电压为AVCC,其中AREF 引脚外加滤波电容 数据右对齐结果选择0通道
ACSR  =(1<<ACD);        //模拟比较器控制和状态寄存器 关闭模拟比较器 这里可以节约电能
ADCSRA=(1<<ADEN)|(1<<ADSC)|_BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0);  //AD使能,禁止自动触发,中断标志,64分频,AD中断不使能,ADC转换启动
}
 
 
 
 
 
 
uint16 ADC_Read(unsigned char Channelx)
{
 
 
uint16 ADTempValue;
ADMUX=0xc0|(Channelx&0x0f);//ADMUX = 0xe0|Channelx; //2.56V 的片内基准电压源, AREF 引脚外加滤波电容 数据右对齐结果
ADCSRA|=(1<<ADSC);      //启动AD转换
loop_until_bit_is_set(ADCSRA,ADIF); //等待AD转换结束其实也可以采用中断方式来读
ADCSRA|=(1<<ADIF);                                             //写1清除标志位
ADTempValue=ADC&0x3ff;                                           //ADC=0000 00ADCH ADCL 共16
  return ADTempValue;
}
 
 
 
 
void Timer0_Init(void)
{
TCCR0 = 0x00; //定时器0的控制寄存器,初始化时停止定时器
TCNT0 = 0x00; //计数器的初始值
OCR0  = 210; //设置比较值 设置为210 8M时钟 大概是38K 实现红外发射
TIMSK|= 0x02; //开比较匹配中断使能
}
 
 
void Timer2_Init(void)
{
TCCR2  = 0x00;              //停止定时器
TCNT2  = 203;               //初始值(1/8000000)*(255-203)=0.0000065
TIMSK |= 0x40; 
}
 
 
void Timer1_Init(void)
{
TCCR1A = 0x00;
TCCR1B = 0x0b;
OCR1AH = 0xf4;
OCR1AL = 0x24;
TIMSK |= 0x10;
}
 
 
 
 
 
 
void Usart1_Init(uint16 baud)
{
UCSRB=0;
//UCSRA为默认值
UBRRL=(FOSC/16/baud-1)%6;//UBRRH = ((uchar8 *)(&baud))[1];
UBRRH=(FOSC/16/baud-1)/256;//UBRRL = ((uchar8 *)(&baud))[0];
UCSRC |=(1<<URSEL)|(3<<UCSZ0); //8位数据
UCSRC &= ~((1<<UPM1)|(1<<UPM0)|(1<<USBS))|(1<<UCPOL);//异步无校验 1个停止位
// UCSRC |=(3<<UCSZ0);
UCSRB |= (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);//UCSRB = (1<<RXEN)|(1<<TXEN)
}
 
 
 
 
//uchar8 Usart_Read(void)
//{
 
 
// UCSRB |= (1<<RXEN);
// loop_until_bit_is_set(UCSRA,RXC);//等待Usart成功接收
// return UDR;
//}
ISR(SIG_USART_RECV)
{
UCSRB &= ~(1<<RXCIE); //关中断
UsartDataBuff=UDR;
 
 
UCSRB |= (1<<RXCIE); //开中断
 
 
}
 
 
 
 
ISR(TIMER0_COMP_vect)
{
PORTD=(PIND&0x9b)|DoubleIRData[BetyCount];
TCCR2  = 0x01;
}
 
 
 
 
 
 
ISR(TIMER2_OVF_vect)
{
PORTD=PIND&0x9F;
TCCR2  = 0;
TCNT2  = 203;
BitCount++;
if(BitCount>=66)//波特率=1/(0.00002625S*66)=577
{
BetyCount++;
if(BetyCount>=20)//25
{
//TCCR0=0;
//TCCR2=0;
BetyCount=0;
}
BitCount=0;
}
}
 
 
ISR(TIMER1_COMPA_vect)
{
SYSCount=1;
}
 
 
void Usart_send(uchar8 data)
{
while(!(UCSRA&(1<<UDRE)));
UDR=data;
}
 
 
int main(void)
{
MCUCR=0x00;
Port_Init();
Timer0_Init();
Timer1_Init();
Timer2_Init();
ADC_Init();
Usart1_Init(581);//581
sei();          //开全局中断关全中断cli()
TCCR0  = 0x09;
TCCR2  = 0x01;
while(1)
{
 
 
if(SYSCount==1)
{
Usart_send(UsartDataBuff);
SYSCount=0;
if(ChargeFlag==1)
{
PORTD|=(1<<PD4);
PORTD&=~(1<<PD3);
}
else
{
PORTD&=~(1<<PD4);
PORTD|=(1<<PD3);
}
if((PORTD&0x80)==0x80)//充电中
{
ADCCurrent1=ADC_Read(1); //电压检测 用
ADCCurrent3=ADC_Read(3); //选3通道 与电路不符 主要因为实验板上0通道损坏 所以跳线3通道修正时间:2014.5.28 
if(ADCCurrent3==0)//电流为0停止供电//0
{
PORTD&=~(1<<PD7);
ChargeFlag=0;
}
}
else
{
ADCCurrent1=ADC_Read(1);
if(ADCCurrent1>=200)//电压大于开始供电//200
{
PORTD|=(1<<PD7);
ChargeFlag=1;
}
else
{
ChargeFlag=0;
}
}
 
 
//UsartDataBuff=Usart_Read();
if(UsartDataBuff)
{
}
}
//i=((uchar8 *)(&k))[0];
//j=((uchar8 *)(&k))[1];
}
}
 
关闭窗口

相关文章