* MEGA8_485_EEPROM_817_ADC_WDT.c
*
* Created: 2013-8-8 16:52:15
* Author: Administrator
*/
#define F_CPU 4000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include <avr/wdt.h>轿雀 //看门狗相关头文件
#include <avr/eeprom.h>
#define INT8U unsigned char
#define INT16U unsigned int
#define INT32U unsigned long
#define BT_NO 0xDE //电池的识别号码
INT8U eepromx EEMEM
//全局变量
INT16U ADC_bt_v
INT8U UART_Send_flag
INT8U ADC_Buffer[]={0,0,0,0}
static INT32U ADC_bt_Total=0
INT16U ADC_bt_S
INT16U ADC_Ref_Buffer[]={0,0}
float ADC_Ref
INT16U n
//串口初始化
void Usart_Init(INT16U BAUD)
{
UCSRB =_BV(RXEN)|_BV(TXEN)|_BV(RXCIE) //接收与发送使能,接收与接收结束中断使能
UCSRC=_BV(UCSZ1)|_BV(UCSZ0)|_BV(UPM1)|_BV(URSEL) //8位数据位、1位停止位、偶校验
UBRRL=(F_CPU/BAUD/16-1)%256 //设置波特率
UBRRH=(F_CPU/BAUD/16-1)/256
}
//单字符发送
void Send_Char(char c)
{
while(!(UCSRA&_BV(UDRE))) //判断数据寄存器是否为空
UDR=c
while(!(UCSRA&_BV(TXC))) //判断发送是否结束
UCSRA|=_BV(TXC) //通过置位进行手动清零
}
//串口接收部分
//#define RX_BUFFER_SIZE 2
//uchar rx_buffer[RX_BUFFER_SIZE]
//uchar rx_counter
//uchar Uart_RecvFlag
//系统初始化
void System_Init()
{
ADCSRA=0xE6 //10位ADC转换置位,启动转换,64分频
DDRB|=_BV(PB0)//485的收发模式控制端口,低电平为接收模式,高电平为发送模式
PORTB&=~_BV(PB0)
DDRC&=~_BV(PC0) //ADC0引脚定义
PORTC&=~_BV(PC0)
TCCR1B=0x03 //T1预设分频:256
TCNT1=65536-F_CPU/64.0*1.5 //晶振4MHZ,1.5S定时初值
TIMSK=0x04 //允许T1定时器溢出中断
wdt_enable(WDTO_2S) //启动看门狗(溢出时间1.9S,约等于2.0S)
/*WDTCSR=0x0F*/
DDRD&=~_BV(PD2) //INT0中断引脚定义竖凯
PORTD|=_BV(PD2)
MCUCR=0x00//INT0中断低电平触发
GICR=0XC0 /闭纤早/INT0中断使能
DDRD&=~_BV(PD3) //INT1中断引脚定义
PORTD|=_BV(PD3)
// EICRA=0x00//INT1中断低电平触发
eeprom_busy_wait()
ADC_Ref_Buffer[0]=(INT16U)eeprom_read_byte(1)
eeprom_busy_wait()
ADC_Ref_Buffer[1]=(INT16U)eeprom_read_byte(2)
ADC_Ref=(float)(ADC_Ref_Buffer[0]*100.0+ADC_Ref_Buffer[1])
DDRC|=_BV(PC4) //测试引脚
PORTC|=_BV(PC4)
sei() //开总中断
}
//------------------------------------------------------------
//对通道CH进行模数转换
//------------------------------------------------------------
INT16U ADC_Convert(void)
{
INT16U Result
ADMUX=0xC0 //ADC0通道,使用内部参考电压1.1V
Result=(INT16U)((ADCL+(ADCH<<8))*ADC_Ref/1024.0*83.0/68.0+ADC_Ref)
return Result
}
INT16U ADC_T()
{
INT16U ADC_bt
ADC_bt=ADC_Convert()
ADCSRA=0xE6
_delay_us(500)//延时后重新再读取ADC,关键点
ADC_bt=ADC_Convert()
ADCSRA=0xE6
return ADC_bt
}
int main(void)
{
Usart_Init(9600)
System_Init()
_delay_ms(1000)
while(1)
{
_delay_ms(10)
}
}
//--------------------------
//外部中断1中断函数
//--------------------------
ISR(INT1_vect)
{
PORTC&=~_BV(PC4)
TIMSK=0X00
}
//--------------------------
//INT0中断函数,用来校正参考电压
//--------------------------
ISR(INT0_vect)
{
//校正参考电压,要用标准2.200V电压来校正
INT16U ADC_C
ADCSRA=0xE6 //10位ADC转换置位,启动转换,64分频
ADMUX=0xC0//ADC0通道,使用内部参考电压1.1V
ADC_C=(INT16U)(ADCL+(ADCH<<8))
ADC_Ref=4035.0/(ADC_C/1024.0*83.0/68.0+1)//要用标准2.200V来校正,精度要尽量高
ADC_Ref_Buffer[0]=ADC_Ref/100
ADC_Ref_Buffer[1]=(INT16U)ADC_Ref%100
eeprom_busy_wait()
eeprom_write_byte(1,ADC_Ref_Buffer[0])
eeprom_busy_wait()
eeprom_write_byte(2,ADC_Ref_Buffer[1])
}
//-------------------------------
//定时器1中断程序负责喂狗(1.9S以内)
//-------------------------------
ISR(TIMER1_OVF_vect)
{
TCNT1=65536-F_CPU/64.0*1.5 //重装初值
wdt_reset() //看门狗复位
}
//USART串口通信接收中断函数
ISR(USART_RXC_vect)
{
INT8U data
data=UDR
sei() //开总中断,实现中断嵌套
UCSRB&=~_BV(RXCIE)
switch (data)
{
case BT_NO:
for (INT8U nn<8n++)
{
ADC_bt_S=ADC_T()
ADC_bt_Total=(INT32U)(ADC_bt_Total+ADC_bt_S)
}
ADC_bt_v=(INT16U)(ADC_bt_Total/8.0)
ADC_bt_Total=0
ADC_Buffer[0]=ADC_bt_v/1000
ADC_Buffer[1]=ADC_bt_v/100%10
ADC_Buffer[2]=ADC_bt_v/10%10
ADC_Buffer[3]=ADC_bt_v%10
PORTB|=_BV(PB0)
_delay_ms(1)
Send_Char(BT_NO) //表明哪个电池分送的信号
_delay_ms(1)
PORTB&=~_BV(PB0)
PORTB|=_BV(PB0)
_delay_ms(1)
Send_Char(ADC_Ref_Buffer[0]) //MCU参考电压高位
_delay_ms(1)
PORTB&=~_BV(PB0)
PORTB|=_BV(PB0)
_delay_ms(1)
Send_Char(ADC_Ref_Buffer[1]) //MCU参考电压低位
_delay_ms(1)
PORTB&=~_BV(PB0)
for (INT8U i=0i<4i++)
{
PORTB|=_BV(PB0)
_delay_ms(1)
Send_Char(ADC_Buffer[i])
_delay_ms(1)
PORTB&=~_BV(PB0)
}
break
}
UCSRB|=_BV(RXCIE)
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)