一乐电子

一乐电子百科

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
查看: 3927|回复: 3
收起左侧

[avr] 求用m8+3位數碼管作倒數器的程序同電路

[复制链接]
发表于 2012-8-6 09:10 | 显示全部楼层 |阅读模式
要求由999不斷倒數000不斷從復,
唔要精確只要簡單,只用m8+3位數碼管作可以嗎,
求各大大幫助
 楼主| 发表于 2012-8-6 09:46 | 显示全部楼层
數碼管型號fnd500
发表于 2012-8-25 22:16 | 显示全部楼层
这个很简单啊,扫描数码管就可以了,程序非常简单的
发表于 2012-8-25 22:17 | 显示全部楼层
//2012年修改 pc0 接18b20

#include <iom8v.h> //和单片机类型相对应的头文件,选择Atmega8做实验;
#include <macros.h>
#include <stdio.h>
#include <eeprom.h>
#include <MATH.H>
#include <stdlib.h>
#include <STRING.H>
#define uchar unsigned char
#define uint unsigned int
#define LED_NUM    PORTD
#define LED_VALUE  PORTB
#define ADC_KEY    3
#define SOUND_OUT  0x08
#define FAN_OUT1   0x01
#define FAN_OUT2   0x02
#define FAN_OUT3   0x04
#define DELAY_MIN  1100
uint v = 0;
uchar adc_channel = 0;
uchar hot_warning[4]={34,34,34,45};
uint  temper[3]={5,5,5};//存放温度
uchar setting_mode = 0;
uchar auto_mode = 0x00;
uchar timeh=0x06;
uchar temp2=0;
uchar PWF1=0;
uchar PWFS1=0,PWFS2=0,PWFS3=0;//是否进行调速标志
uchar Fc1,Fc2,Fc3;//计数
void init_1820();//初始化1820                                                                               
write_1820(uchar x); //写参数到1820
uchar read_1820(); //读温度
void delay(uint x);
void disp_led(uchar buffer,uchar control);
void test(void);
void delay_1ms(void);
//uchar hot_warning[4]={30,35,40,45};//设定风扇启动温度
void delay_nms(unsigned int n);
unsigned int wendu[4]={21,22,23,24};//定义温度存放数组
void temph(unsigned int tx); //电压转换成温度
void display(void);// 显示数据
void display_mode(uchar mo);//模式显示,花样显示
void scandisplay(uint value);//扫描显示数码管
void dc_save(void);//dc 转换结果存储后用
void init_port();//初始化端口
void output(uchar channel,uchar power);//风扇控制 函数 通道  风力
unsigned int  uiVref_preset=4996;         // 参考电压=2665mV
uchar Lednum[4]={0xEF,0xDF,0xBF,0x7F};//数码管公共端口
uchar  disp_table[17] = {
        0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
        0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x40,0};
        //共阴数码管       
const uint v_table[135]={
950,1000,1050,1100,1150,1200,1250,1300,1350,1400,//-10-1
1450,1500,1550,1600,1650,1700,1750,1800,1850,1900//0-9
,1950,2000,2050,2100,2150,2200,2230,2260,2290,2320//10-19
,2350,2380,2410,2440,2470,2520,2590,2600,2617,2670//20-29
,2725,2800,2855,2935,2990,3041,3100,3148,3206,3260
,3302,3354,3414,3450,3504,3554,3600,3650,3680,3748
,3778,3818,3850,3889,3936,3986,4008,4015,4059,4089
,4116,4124,4146,4170,4200,4224,4248,4275,4296,4314
,4332,4353,4374,4395,4416,4428,4444,4461,4476,4488
,4502,4528,4544,4552,4562,4574,4584,4594,4602,4612
,4622,4632,4642,4652,4660,4668,4672,4680,4690,4698
,4704,4713,4723,4728,4733,4738,                                               
                                                };
const uchar sound[]={ //?Ρ?誹?
        0x45,0x48,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x49,0x4a,
        0x49,0x48,0x48,0x48,0x48,0x48,0x45,0x48,0x4a,0x4a,
        0x48,0x4a,0x4c,0x4c,0x4b,0x4a,0x49,0x49,0x49,0x49,
        0x49,0x4c,0x4b,0x4a,0x4a,0x4a,0x49,0x48,0x48,0x49,
        0x4a,0x4c,0x4b,0x4b,0x4b,0x4b,0x4b,0x46,0x46,0x45,
        0x45,0x45,0x47,0x48,0x49,0x49,0x4a,0x49,0x48,0x48,
        0x48,0x48,0x48,0x48,
        0x00,0x00
};               
uchar temp1[6];
uint count;
#define PWM0                        3         //OC0   PB3
#define PWM1A                        5         //OC1A  PD5
#define PWM1B                        4         //OC1B  PD4
#define PWM2                        7         //OC2   PD7
#define   Fosc           4096000          //系统晶振频率 4.096MHz
#define   Fosc_TIME2      (64*10)             //TIME2 比较中断频率=采样率*AD通道数*工频50Hz的倍数
volatile unsigned char T2PWM;       
void main(void)
{   
    uint i,k;
        int j;       
        uchar temh,teml;
  init_port();//初始化       
  hot_warning[0] = EEPROMread(0x01);  //读取报警温度
  hot_warning[1] = EEPROMread(0x02);
  hot_warning[2] = EEPROMread(0x03);  
     for(k=0;k<4;k++) //初始化
      {
           if (hot_warning[k]>120)
            hot_warning[k]=32;
      }       
  while(1)
  {   init_1820();        //复位18b20
                write_1820(0xcc);   // 发出转换命令
                write_1820(0x44);
                delay(400);
                                 //scandisplay(count);
                init_1820();
                WDR();
                write_1820(0xcc);  //发出读命令
                 //scandisplay(count);
                                write_1820(0xbe);
                teml=read_1820();  //读数据
                temh=read_1820();
                count=((temh*256+teml)*6.25)/10;  //计算具体温度
                scandisplay(temh);
  }

}

//io口初始化
void init_port()
{
           OSCCAL=0X9d;   //系统时钟校准,不同的芯片和不同的频率,
          //DDRB=0x03;     //定义B口的PB0、PB1为输出口
          //DDRC=0x30;     //定义C口的PC4和PC5为输出口
        //PORTD = 0x01;  //pd2.pd3.pd4输入 pd0 输出
    //DDRD  = 0x01;
    //CLKPR = 0x80;
   // CLKPR = 0x00;   
    DDRB = 0xff;
    PORTB = 0xff;
    DDRC = 0x00;
    PORTC = 0x00;
         DDRB = 0xff;
     PORTB = 0xff;
    DDRD  = 0xFF;//定义PD0喇叭输出 PD2 PD3 PD4 按键输入 PD5 PD6 PD7 风扇输出
        PORTD = 0xF7; //初始化 端口 数据
        WDR();        //看门狗计数清零
    WDTCR=0x0F;    //使能watchdog,并且,采用2048K分频,典型溢出时间5V时2.1S
    //adc_init();                // 使能ADC
        //timer2_init();             // 使能AD转换
        CLI();
    ADMUX = (1<<REFS0);    //选择基准
    ADCSRA = (1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1);        
         MCUCR = 0x00;
     GICR  = 0x00;
    TIMSK = 0x15; //timer interrupt sources       
        SEI();       //开放中断
          //WDTCSR = 0x0F;
        //PORTB=0B00000010; //PB1口输出高电平,PB0口输出低电平,关闭绿灯,红灯亮
          //delay_nms(500); //延时1秒
        temp1[1]=1;
        temp1[2]=2;
        temp1[3]=3;
        //test();
        timer0_init();
        timer1_init();
}
//TIMER0 initialize - prescale:1024
// desired value: 60mSec
// actual value: 59.904mSec (0.2%)
void timer0_init(void)
{
TCCR0 = 0x00; //stop
TCNT0 = 0x16; //set count
TCCR0 = 0x05; //start timer
}
#pragma interrupt_handler timer0_ovf_isr:10
void timer0_ovf_isr(void)
{
TCNT0 = 0x16; //reload counter value
}


//数码管 扫描显示

void scandisplay(uint value)
{     
      uchar i,j,k,l;
          uint tempvalue;
      uchar led_data[4];
led_data[3]=16;
if ((value & 0x8000)==0x8000)
  {
      value &= 0x7fff;
      led_data[2] = 15; // 顯示負號
  }
  else
  {
      value &= 0x7fff;
           if(value<999)//需要加小数点
      {
       k=1;
           led_data[2] = value/100;
       }
     else
     {
      k=0;
          value=value/10;
          led_data[2] = value/100;
     }          
  };

led_data[1] = value%100/10;
led_data[0] = value%100%10;
if((led_data[2]==0)&&(led_data[1]==0))
{//如果只有1位数的时候,将高位的0去掉
led_data[2]=16;
led_data[1]=16;
k=0;//去掉小数点
}
    for (j=0;j<10;j++) //刷新20次 避免数据跳动
     {  
         for (i=0;i<4;i++)
      {
                LED_VALUE = disp_table[led_data[i]];
        if((i==1)&&(k==1))
        {   
            LED_VALUE |= 0x80; // 加上小數點
        }
                LED_NUM&=Lednum[i];//对应位数码管点亮
                delay_nms(10);
           LED_NUM|= 0xF0;//只保留高3位为1
      };
     };
}

void delay_1ms(void)//1ms延时函数
{
  unsigned int i;
  for (i=0;i<150;i++);
  WDR();    //清看门狗
}
void delay_nms(unsigned int n)//延时n毫秒
{
  unsigned int i;
  for (i=0;i<n;i++)//执行n次1毫秒延时
  delay_1ms();
}
#pragma interrupt_handler adc_isr:iv_ADC
void adc_isr(void)
{  uint temp;
  temp = ADCL;
  temp |= (int)ADCH<<8;  
  temp = (50*temp)/10;
  v += temp;   
}
void get_adc_value(uchar adc_pin)
{  
  uchar i;
  v = 0x0000;
  ADMUX = (1<<REFS0)|adc_pin;
  {
  ADCSRA |= (1<<ADSC);
  delay_nms(1);  
  ADCSRA &= ~(1<<ADSC);  
  }  
}
uint get_degree(void)
{
  uchar x,y;
  uint v_big,v_small,v_step;
  if (v<100) return 0x83E7; // 當沒有信號時顯示-99.9錯誤
  for (x=0;x<135;x++) // 查表
  {
      if ( v>= v_table[x]) // 找出電壓區域 //
      {
        v_big = v_table[x+1]; // 區域 高段
        v_small = v_table[x]; //區域 低段
        v_step = (v_big - v_small)/10; // 把區域細分成10份
        for (y=0;y<10;y++) // 細分比較
        {
            v_small += v_step;
            if (v < v_small) // 得出結果
            {
              v = x*10+y;// 其中x*10 為整數部分, y 為小數部分
              if (x<10) // 少於10時為負溫度
              {
                           // v -= 400; // 0 度修正
                  v |= 0x8000; // 加入負號標記
                                  //v=v;
              }
              else
              {
               v -= 100; // 0 度修正
              }
                         
                  return v;  //返回温度
            };
        };
      };
      WDR();
  }  
  return v;   
}
uchar get_key_value(void)
{
        get_adc_value(ADC_KEY);
        if (v < 250)
        {
                return 0;
        }
        else
        {
                if ((v > 1000)&&(v < 1300))
                {
                        return 1;//1150mv
                }
                else
                {
                        if ((v > 1300)&&(v < 2200))
                        {
                                return 2;//1948
                        }
                        else
                        {
                                if ((v > 2200)&&(v < 3500))
                                {
                                        return 3;//3000mv
                                }
                                else
                                {
                                        return 0;
                                }
                        }
                }
        }
}

void temp_setting(void)
{
        uchar key;
        key = get_key_value();

        if(key==2)
        {
                adc_channel++;

                if (adc_channel>2) //切换显示路数
                  {
                   adc_channel = 0;
                   }
       scandisplay(adc_channel+1);
           scandisplay(adc_channel+1);
           scandisplay(adc_channel+1);
           scandisplay(adc_channel+1);               
        }
        if(key==3)
        {
           if (auto_mode==0xff) // 自動模式
        {
                auto_mode = ~auto_mode;//退出 自动模式
                }
               
                if (adc_channel==0) //设置模式
                {
                        adc_channel = 1;
                        auto_mode = ~auto_mode;//3路自动切换
                }
                adc_channel--;               
        }
        while(1)
        {
                get_adc_value(ADC_KEY);
                if(v < 200) //退出当前模式
                {
                        break;
                };
        };       
        if (key==1)
        {
        scandisplay(1+adc_channel);
        scandisplay(1+adc_channel);
        scandisplay(1+adc_channel);       
        scandisplay(1+adc_channel);       
        setting_mode = 1;
        }

        while(setting_mode==1)
        {
                key = get_key_value();
                if(key==1)
                {
            adc_channel++;                                       
                        if (adc_channel>2)
                        {
                                adc_channel = 0;
                                setting_mode = 0;
                                EEPROMwrite(0x01, hot_warning[0]);
                                delay_nms(5);
                                EEPROMwrite(0x02, hot_warning[1]);
                                delay_nms(5);
                                EEPROMwrite(0x03, hot_warning[2]);
                                delay_nms(5);
                        }
           scandisplay(1+adc_channel);
           scandisplay(1+adc_channel);
           scandisplay(1+adc_channel);
           scandisplay(1+adc_channel);                                       
                }
                else
                {
                        if(key==2)
                        {
                            if(hot_warning[adc_channel]>105)
                                {
                                hot_warning[adc_channel]=30;
                                }
                                else
                                {
                                ++hot_warning[adc_channel];
                                }
                        }
                        else
                        {        if(key==3)
                            {
                            if(hot_warning[adc_channel]<1)
                                {
                                hot_warning[adc_channel]=30;
                                }
                            else
                                {
                                 --hot_warning[adc_channel];
                                }
                                }
                        };
                };
                while(1)
                {
                        get_adc_value(ADC_KEY);
                        if(v < 200)
                        {
                                break;
                        };
                };
                scandisplay(hot_warning[adc_channel]*10);
        }
}
  
//TIMER1 initialize - prescale:1024
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 500mSec
// actual value: 499.968mSec (0.0%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0xFF; //setup
TCNT1L = 0xFC;
OCR1AH = 0x07;
OCR1AL = 0xA1;
OCR1BH = 0x07;
OCR1BL = 0xA1;
ICR1H  = 0x07;
ICR1L  = 0xA1;
TCCR1A = 0x00;
TCCR1B = 0x05; //start Timer
}

#pragma interrupt_handler timer1_compa_isr:7
void timer1_compa_isr(void)
{
//compare occured TCNT1=OCR1A
}
#pragma interrupt_handler timer1_ovf_isr:9
void timer1_ovf_isr(void)
{
//TIMER1 has overflowed
//TCNT1H = 0xF8; //reload counter high value
TCNT1H = 0xFF;
TCNT1L = 0xFC; //reload counter low value
  //PORTD=bitcpl(PORTD,2);// 取反 。。。
  // scandisplay(995);
  Fc1++;
  pwm1();
  Fc2++;
  Fc3++;
  //pwm2();

}

void pwm1(void) // pwm 控制函数
{
//开始 调速控制
if(PWFS1)
  {
    //输出
         if(Fc1<45)
         {
         PORTD=bitset(PORTD,0);//打开风扇
         }
    else
     {
     PORTD=bitclr(PORTD,0);//关闭风扇
     }
     if(Fc1>90)
     {
     Fc1=0;
     }
  }
     //输出
        if(PWFS2)
        {
         if(Fc2<45)
         {
         PORTD=bitset(PORTD,1);//打开风扇
         }
    else
     {
     PORTD=bitclr(PORTD,1);//关闭风扇
     }
     if(Fc2>90)
     {
     Fc2=0;
     }
   }
     //输出
        if(PWFS3)
        {
         if(Fc3<45)
         {
         PORTD=bitset(PORTD,2);//打开风扇
         }
    else
     {
     PORTD=bitclr(PORTD,2);//关闭风扇
     }
     if(Fc3>90)
     {
     Fc3=0;
     }
   }
}
uchar bitclr(uchar num,uchar bit) /*清除某一位*/
{
uchar bit_value[]={1,2,4,8,16,32,64,128};
return num&~bit_value[bit];
}
uchar bitset(uchar num,uchar bit) /*设置某一位*/
{
uchar bit_value[]={1,2,4,8,16,32,64,128};
return num|bit_value[bit];
}
uchar bitcpl(uchar num,uchar bit) /*取反某一位*/
{
uchar bit_value[]={1,2,4,8,16,32,64,128};
if(num>>bit&0x01==1)
return num&~bit_value[bit];
else
return num|bit_value[bit];
}
void init_1820()
{
         PORTC|=(1<<0);   
         PORTC&=~(1<<0);
         delay(3000);    //480us以上
            PORTC|=(1<<0);
         DDRC&=~(1<<0);
         delay(40);     //15~60us
         while(PINC&(1<<0))
         {
           // disp_led(3,0);
                // for(;;)
                 //{}
        }
         DDRC|=(1<<0);
         PORTC|=(1<<0);
         delay(150);   //60~240us
}
write_1820(uchar x)
{   
     uchar m;
         for(m=0;m<8;m++)
         {
              PORTC&=~(1<<0);
                 if(x&(1<<m))    //写数据,从低位开始
                 PORTC|=(1<<0);
                 else
                 PORTC&=~(1<<0);
                 delay(40);   //15~60us
                 PORTC|=(1<<0);
         }
          PORTC|=(1<<0);
}


uchar read_1820()
{     
         uchar temp,k,n;
           temp=0;
         for(n=0;n<8;n++)
            {
                PORTC&=~(1<<0);
                //delay(2);      
                PORTC|=(1<<0);
                //delay(3);     
                DDRC&=~(1<<0);
                k=(PIND&(1<<0));    //读数据,从低位开始
                if(k)
                temp|=(1<<n);
                else
                temp&=~(1<<n);
                delay(50); //60~120us     
                DDRC|=(1<<0);
        }
        return (temp);
}  

void delay(uint x)  //1.5us左右
{
          while(x)
         {
            x--;
         }
}

本版积分规则

QQ|一淘宝店|手机版|商店|电子DIY套件|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2024-5-18 05:24 , Processed in 0.061424 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表