打印
[AVR单片机]

AVR程序求教

[复制链接]
3205|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
justlose|  楼主 | 2013-5-15 22:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
//★DC45V6_ATtiny13 CPU,与48相比,SFR有较大的差别  采样电阻30K!
//★内部RC震荡4.8MHz,CPU 8分频。定时器再8分频。
//把DWEN=1,RSTDSIBL=0两位同时设置(打钩)才能作为普通I/O口用!!!
//一旦“烧死”,程序不能再下载,须用高压编程器重新变成。
//BODLEVEL: VCC=4.3V;CKDIV8 √; SUT_CKSEL:int RS OSC 4.8MH 14CK+4sm
//主要思路:采样电容充电电压(R1/R2="STR"),达到额定电压的85%时,启动电磁铁(得电)。
//采样电磁铁工作电压(R3/R4="U50",并用5V1稳压管限幅),电源电压降到50%时,停止电磁铁(断电)。
//程序写入时,选择“Int…RC…6CK/14CK+0ms”,防止电磁铁“抖动”!
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
//注:内部函数_delay_ms() 最高延时  262.144mS@1MHz 即 32.768ms@8MHz
#include <avr/sleep.h>

//时钟内部8M,经内部DIV8后系统时钟为1MHz★
#define        uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define        NOP         asm("nop")

//电压
uint        U85=985;                        //85% (电磁铁未工作时的饱和电压4.48V)        380V参数(采样电阻17K7)        (最佳300V~310V)               
uint        U50=245;                        //50% (采样电磁铁吸合后的工作)非线性电压 260mV                                        (最佳200V~210V)
uint        U30=145;                        //30% (采样电磁铁吸合后的工作后电压,对应电源电压30%)

//定义延时时间
#define        T0_1MS                0xb5        //4.8/8/8=0.075MHz,1000*0.075=75,256-75=181=b5H(系统4.8MRC,CPU时钟8分频)

//延时时间
#define        DL_CNT0                0                //0S
#define        DL_CNT1                80                //1S 每10mS减一,加入零压保持电容后,断电响应时间变慢600mS
#define        DL_CNT2                170                //2S
#define        DL_CNT3                250                //3S
#define        DL_CNT4                340                //4S
#define        DL_CNT5                430                //5S
#define        DL_CNT6                520                //6S
#define        DL_CNT10        940                //10S

//管脚定义
#define adc_SA                1                 //ADC3

//-----------位操作定义----
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))

#define        CH_ON        cbi(PORTB,3)        //低电平,充电。电容充电回路
#define        CH_OFF        sbi(PORTB,3)        //高电平,关闭
#define        DCT_ON        sbi(PORTB,0)        //低电平,电磁铁得电。电磁铁控制
#define        DCT_OFF        cbi(PORTB,0)        //高电平,电磁铁失电

// 全局变量
uint        ad_array[10];                        //10次AD存储值        array
uchar        tim_10cnt;                                //10ms计数器
uchar        f_1ms;                                        //1ms中断
uint        delay_data=0;                        //设定的延时时间
uint        dl_cnt;                                        //延时计数器,10ms减1
uchar        state=0;                                //状态计数器
uchar        key_10ms;                                //键盘扫描,每10ms扫描一次

//**********************************************************************************
void timer0_init(void)                        //T0定时1ms
{
        TCCR0A = 0x00;                                 //T/C 控制寄存器A:COM0A1 COM0A0 COM0B1 COM0B0 – – WGM01 WGM00
        TCCR0B = 0x00;                                 //T/C 控制寄存器B:FOC0A FOC0B – – WGM02 CS02 CS01 CS00
        TCNT0 = T0_1MS;                         //设定时间常数       
        TCCR0B = 0x02;                                 //start timer--8分频--1M内部系统时钟--1ms中断一次
        TIMSK0 = 0x02;                          //★T/C 中断屏蔽寄存器:– – – – OCIE0B OCIE0A TOIE0 –,溢出中断TOIE0       
}

//**********************************************************************************

void adc_init(void)
{                                                                //【ADCSRA 控制及状态寄存器】:ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0
    ADCSRA=0x03        ;                           //时钟8分频 125KHz@1MHz system clock       
    ADCSRA &=~(1<<ADEN);                //禁止ADC
    ADMUX=0x01;                                    //★VCC作为参考电压,第1路输入ADC1)     
}

//**********************************************************************************

void WDT_off(void)
{
        MCUSR &= ~(1<<WDRF);                                //清除MCUSR 寄存器中WDRF
        WDTCR |= (1<<WDCE) | (1<<WDE);                //在WDCE 与WDE 中写逻辑1 保持旧预分频器设置防止无意暂停
        WDTCR = 0x00;                                                //关闭WDT
}

//**********************************************************************************

void main_init(void)                        //DDRB PORTB
{
        DDRB=0x09;                                        //b0000_1001;PB4电容充电(初高)、PB0输出控制电磁铁(初低)
        PORTB=0xfa;                                        //b1111_1010;(★PB2为AD输入,无上拉电阻-高阻态)
        PCMSK=0x00;                                        //引脚变化屏蔽寄存器– – PCINT5 PCINT4 PCINT3 PCINT2 PCINT1 PCINT0(全禁用)
        ACSR=0x80;                                        //模拟比较器控制及状态寄存器ACD(关闭) ACBG ACO ACI ACIE – ACIS1 ACIS0
        DIDR0=0x08;                                        //数字输入禁用寄存器0(模拟比较器关)– – ADC0D ADC2D ADC3D ADC1D AIN1D AIN0D
        ACSR=(1<<ACD);                                //模拟比较器(上电默认是打开的,需要手工关闭)
        timer0_init();                               
        adc_init();
        WDT_off();
}

//**********************************************************************************

unsigned int read_adc(uchar adc_port)        //查询方式读取ADC单端通道
{
    uchar i;                                                        //ADMUX【多路复用选择寄存器】:– REFS0 ADLAR – – – MUX1 MUX0
    ADCSRA |=(1<<ADEN);                                        //ADEN=1,使能ADC     ADMUX=(0x40|adc_port);
                                                                            //★AD端口号及 “adc_port”参考电压,已给定
    for(i=10;i>0;i--);                                        //延时等待稳定
    ADCSRA|=(1<<ADSC);                                        //启动AD转换ADC
    loop_until_bit_is_set(ADCSRA,ADIF);        //ADIF=1时后,AD转换结束
    ADCSRA|=(1<<ADIF);                                        //写1清除标志位
    ADCSRA &=~(1<<ADEN);                                //ADEN=0,禁止ADC
    return ADC;                                                        //ADC=ADCH:ADCL
}
//**********************************************************************************

//取10个数maxmin取平均
unsigned int ad_lb(uint ad_tmp[])
{
        ulong temp=ad_tmp[0];
        uchar i=1;
        uint  max=ad_tmp[0],min=ad_tmp[0];
        for(i=1;i<10;i++)
                {
                        temp+= ad_tmp[i];
                        if(ad_tmp[i]>max)
                        {
                                max=ad_tmp[i];
                        }
                                else if(ad_tmp[i]<min)
                                {
                                        min=ad_tmp[i];
                                }               
                }
        temp=(temp-max-min)/8;
        return (uint)temp;
}

//**********************************************************************************

SIGNAL(TIM0_OVF_vect)                                                        //T0溢出中断1ms
{
        TCNT0 = T0_1MS;       
        f_1ms=1;
}
       
//**********************************************************************************
void vol_deal(uint volt_ad)                                                //电压处理
{
        switch(state)
        {
                case 0:
                {                                                                                //断开态
                        if(volt_ad>U85)                                                //>85%吸合 全导通
                        {
                                DCT_ON;                                                        //启动电磁铁得电
                                _delay_ms(100);                                        //延时100mS
                                _delay_ms(100);                                        //延时100mS
                                CH_ON;                                                        //电容开始充电
                                _delay_ms(100);                                        //延时100mS
                                state=1;
                                _delay_ms(10);                                        //延时100mS
                               
                        }
                        break;
                }       
                case 1:
                {                                                                                //吸合态
                        if(volt_ad<U50)                                                //电压低于50%,进入断电延时
                        {       
                                if(delay_data==0)
                                {
                                        DCT_OFF;                                        //关闭电磁铁(断电)
                                        CH_OFF;                                                //关闭电容充电
                                        _delay_ms(5);
                                        state=0;
                                }
                                else
                                {
                                        dl_cnt=delay_data;
                                        state=2;
                                }                                       
                        }
                        break;
                }
                case 2:                                                                        //延时中……
                {
                        if(volt_ad>U50)                                                //停止延时,返回正常状态
                        {
                                state=1;
                        }
                                else if((--dl_cnt==0))                        //零压延时                               
//                                else if((--dl_cnt==0)||(volt_ad<U30))       
                                {
                                        DCT_OFF;                                        //关闭电磁铁(断电)
                                        CH_OFF;                                                //关闭电容充电
                                        state=0;                                        //延时完成
                                }
                        break;
                }       
                  default:  
                  {
                          state=0;
                        break;                                               
                  }
        }
}

//**********************************************************************************

void vol_judgment(void)
{
        uint ad_dat;
        ad_array[tim_10cnt]=read_adc(adc_SA);
       
        if(++tim_10cnt==10)                                                        //10ms处理一次 交流半周期波形(每个周期测10个点)
                {
                        tim_10cnt=0;                                               
                        key_10ms=1;                                                        //key_10ms=1;
                        ad_dat=ad_lb(ad_array);
                        vol_deal(ad_dat);
                }
        if(state==0)
            {
            ADMUX&=~(1<<REFS0);                                                //★(切换到)VCC作为参考电压
            }                                                               
            else
                    {
                    ADMUX|=(1<<REFS0);                                        //★(切换到)片内基准电压1.1V
                    }       
}

//******************************************************************************
void key_scan(void)
{
        uchar key_state;
        key_state = PINB;                                                        //读引脚
        key_state &=0x32;                                                        //得到按键状态
                switch(key_state)                                                //延时时间        (0S)(1S)(2S)(3S)(4S)(5S)(6S)(10S)
                {
                        case 0x32:delay_data=DL_CNT0;break;
                        case 0x30:delay_data=DL_CNT1;break;
                        case 0x22:delay_data=DL_CNT2;break;
                        case 0x20:delay_data=DL_CNT3;break;
                        case 0x12:delay_data=DL_CNT4;break;
                        case 0x10:delay_data=DL_CNT5;break;               
                        case 0x01:delay_data=DL_CNT6;break;               
                        case 0x00:delay_data=DL_CNT10;break;
                        default:delay_data=DL_CNT0;break;
                }
}

//**********************************************************************************
int main(void)
{       
        uchar temp=0;
        main_init();
        _delay_ms(100);                                                                //延时100mS
        _delay_ms(100);                                                                //延时100mS
        _delay_ms(100);                                                                //延时100mS,等待电容充电稳定
        sei();                                                                                //使能全局中断
               
        while(1)
        {
                if(f_1ms==1)
                        {
                        f_1ms=0;       
                        vol_judgment();                                                //电压判断
                        }
                if(key_10ms==1)
                        {
                        key_10ms=0;
                        key_scan();                                                        //延时开关扫描
//                        delay_data=DL_CNT0;                                        //瞬时实验
                        }
                set_sleep_mode(SLEEP_MODE_IDLE);                //设定空闲模式
                sleep_mode( );                                                        //0.52mA
        }
}


求解程序的中文解释,最好把其中宏定义的数字选择原因说一下

相关帖子

沙发
huangxz| | 2013-5-16 10:27 | 只看该作者
楼主是留学生么;P

使用特权

评论回复
板凳
justlose|  楼主 | 2013-5-16 20:53 | 只看该作者
huangxz 发表于 2013-5-16 10:27
楼主是留学生么

本科即将被留级,算是留学生吗

使用特权

评论回复
地板
quzhanguang| | 2013-5-16 21:54 | 只看该作者

使用特权

评论回复
5
qin552011373| | 2013-5-16 23:32 | 只看该作者
后面注释不是中文解释么

使用特权

评论回复
6
justlose|  楼主 | 2013-5-16 23:44 | 只看该作者
qin552011373 发表于 2013-5-16 23:32
后面注释不是中文解释么

我遇到瓶颈了,当假设第一次执行完switch(state)后(其中执行的是case 0,且满足条件语句),state变为1,接着进入if(state)条件判断,执行完后,在执行if(key_10ms==1)条件判断,接着就进入空闲模式,这时是不是就终止程序。还是继续while(1)循环,还有一个问题就是溢出中断能指导下到底是什么情况下发生,语言组织有些不畅,希望能看懂。如果会的话,希望能帮我把问题解决下,谢谢了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

3

帖子

0

粉丝