⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 21010012.txt

📁 极低功率UHF无线收发器 315/433/868和915MHz ISM/SRD波段系统 AMR-自动仪表读数 电子消费产品 RKE-两路远程无键登录
💻 TXT
字号:
/*******************************
project        :A/D转换数码管显示
chip type      : atmega8		
clock frequency:内部RC(INT) 8MHz
Author         :周远峰		
********************************/
#include "iom8v.h"
#include "macros.h"
#define osccal 0x7d      		   
unsigned long adc_rel;              //处理后世界转换结果
unsigned long adc_rl;               //A/D转换结
unsigned int tmp;                   //设置的温度参数  			
unsigned char adc_mux;              //A/D通道 
unsigned char led_buff[3]={0,0,0};  //显示缓存
signed int error0;                  //当前偏差
signed int error1;                  //上次偏差
signed int error2;                  //上上次偏差
signed char Kp;                     //比例常数
signed char Ki;                     //积分常数
signed char Kd;                     //微分常数
signed int kk1;                     //当前控制输出
signed int kk2;                     //上次控制输出
#define NB -3
#define NM -2
#define NS -1
#define ZO 0 
#define PS 1 
#define PM 2
#define PB 3
#pragma data:code     
 //设置数据区位程序储存器
const unsigned char seg_table[16]={0x40,0x79,0x24,0x30,0x19,0x90,0x80,0x78,0x00,0x10,0x08,0x81,0x44,0x21,0x04,0x8c};
const unsigned char KP_table[49]={PB,PB,PM,PM,PS,ZO,ZO,PB,PB,PM,PS,PS,ZO,NS,PM,PM,PM,PS,ZO,NS,NS,PM,PM,PS,ZO,NS,NM,NM,PS,PS,ZO,NS,NS,NM,NM,PS,ZO,NS,NM,NM,NM,NB,ZO,ZO,NM,NM,NM,NB,NB};
const unsigned char KI_table[49]={NB,NB,NM,NM,NS,ZO,ZO,NB,NB,NM,NS,NS,ZO,ZO,NB,NM,NS,NS,ZO,PS,PS,NM,NM,NS,ZO,PS,PM,PM,NM,NS,ZO,PS,PS,PM,PB,ZO,ZO,PS,PS,PM,PB,PB,ZO,ZO,PS,PM,PM,PB,PB};
const unsigned char KD_table[49]={PS,NS,NB,NB,NB,NM,NS,PS,NS,NB,NM,NM,NS,ZO,ZO,NS,NM,NM,NS,NS,ZO,ZO,NS,NS,NS,NS,NS,ZO,ZO,ZO,ZO,ZO,ZO,ZO,ZO,PB,NS,PS,PS,PS,PS,PB,PB,PM,PM,PM,PS,PS,PB};
#pragma data:data    
//设置数据区回到数据储存器
/*********************************************************

延时函数

*********************************************************/
void delay_us(int time) //微秒级延时
 {
 do
 time--;
 while (time>1);
 }
 void delay_ms(unsigned int time)  //毫秒级延时
 {
 while (time!=0)
   {
   delay_us(1000);
   time--;
   }
 }
 /************************************************************
中断显示初始化
TIMER2 initialize - prescale:1024
WGM: Normal
desired value: 10mSec
actual value:  9.984mSec (0.2%)
*************************************************************/
void timer2_init(void) 
{
 TCCR2 = 0x00; //stop
 ASSR  = 0x00; //set async mode
 TCNT2 = 0xB2; //setup
 OCR2  = 0x4E;
 TCCR2 = 0x07; //start
 DDRB=0xff;  //PC口为推挽1输出
 PORTB=0xff; //PC口内部上拉
 DDRD|=0xf1;
 PORTD&=0x1f;  //关闭LED
}
/***********************************************

中断显示

*************************************************/
#pragma interrupt_handler timer2_ovf_isr:5
void timer2_ovf_isr(void)
{
 unsigned char i;
 static unsigned k;
 SEI();
 TCNT2 = 0xB2; //reload counter value
 for(i=0;i<3;i++)
   {
   PORTB=led_buff[i];
   PORTD|=(1<<(i+5));//待显示的位置1
   delay_ms(1);
   PORTD&=0x1f;     //关闭LED
   }
}
/************************************************************

PWM初始化,OC1A口输出

*************************************************************/
void timer1_init(void) 
{
 TCCR1B = 0x00; //stop
 TCNT1H = 0x00; //setup
 OCR1A  = 200;
 TCCR1A = (1<<WGM11)|(1<<WGM10)|(1<<COM1A1);//输出低电平 
 TCCR1B = (1<<CS11)|(1<<CS10); //
}
/*****************************************************

PID初始化

******************************************************/
void pidcalc_init(void)  
{
Kp=3;
Ki=3;
Kd=3;
kk1=0; //当前
kk2=100;
error0=0;
error1=0;
error2=0;
tmp=300;
}
void pidcalc_zizheng(void)
{
if (tmp>adc_rel)
   { 
	if (kk2<500) kk2+=3;
	else kk2=500;
   }
if ((tmp-1)>adc_rel)
   { 
	if (kk2<500) kk2+=3;
	else kk2=500;
   }
/*if ((tmp-2)>adc_rel)
   { 
	if (kk2<600) kk2+=3;
	else kk2=600;
   }*/
if (tmp<adc_rel)
   {
   if (kk2>10) kk2-=3;
   else kk2=10;
   }
if ((tmp+1)<adc_rel)
   {
   if (kk2>10) kk2-=3;
   else kk2=10;
   }
/*if ((tmp+2)<adc_rel)
   {
   if (kk2>10) kk2-=3;
   else kk2=10;
   }
/*if (tmp>adc_rel)
   {
   if (Ki<200) Ki+=4;
   else Ki=400;
   }
if (tmp<adc_rel)
   {
   if (Ki>0) Ki-=4;
   else Ki=0;
   }  */ 
}
/*******************************************************

PID函数

********************************************************/
void pidcalc(void)
{
signed long KPP;
signed long KII;
signed long KDD;
signed int i;
signed char j;
error0=tmp-adc_rel;
j=error0-error1;
i=7*(3+error0)+(3+j);
if(i<49)
    {
     if (i>0)
	    {
		Kp=KP_table[i];
		Ki=KI_table[i];
		Kd=KD_table[i];
		} 
     }                        //输出	              
if ((tmp-15)<adc_rel)                         //比设定低一定值时开始PID
  {
   if((tmp+5)>adc_rel)                        //比设定高时关PID
       {
       KPP=Kp*(error0-error1);                //比例
       KII=error0*Ki;                         //积分
       KDD=Kd*(error0-(2*error1)+error2);     //微分
       kk1=(KPP+KII+KDD)*4+kk2;  
       if(kk1<0x3ef)
	           {
			   if (kk1>=10) OCR1A=kk1;   
			   else OCR1A=0;                
               }
	   else
	           {   
	            OCR1A=0x3ff;
               }      
			   /*if((tmp-2)>adc_rel)
			        {
			        if(OCR1A<500) OCR1A+=20;
			        else OCR1A=500;
					}*/
	   }
    else 
	   {
	   //if (tmp<adc_rel)
	         // {
	          ///  if (OCR1A>50) OCR1A-=20;
	          //  else OCR1A=50;
	   OCR1A=0;  
	         // }
       }
   }
else
   { 
    OCR1A=0x3ff;
   }
error2=error1;
error1=error0;  
}
/***********************************************

ADC初始化

************************************************/
void adc_init(void)  
 {
 DDRC=0x00;
 PORTC=0X00;
 ADCSRA=0X00;
 ADMUX=(1<<REFS1)|(1<<REFS0)|(adc_mux&0x0f); //选择内部2.56V为基准AREF外加滤波电容
 ACSR=(1<<ACD);                  //关闭模拟比较器
 ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);//128分频
 }
 /*********************************************
 
 ADC中断处理函数
 
 **********************************************/
 #pragma interrupt_handler adc_isr:15
 void adc_isr(void)
 {
 static unsigned i;
 adc_rl+=ADC&0x3ff;
 ADMUX=(1<<REFS1)|(1<<REFS0)|(adc_mux&0x0f); //选择内部2.56V位基准
 ADCSRA|=(1<<ADSC); //启动AD转换   
 if (i<2048)
    i++;
else  
     {
	 adc_rel=adc_rl/2048;
	 adc_rel=adc_rel*3/5;
	 i=0;
	 adc_rl=0;
	 }
 }
 /******************************************************
 
 ADC数据转压缩BCD
 
 ******************************************************/
 void ADCtoBCD(unsigned int temp) 
 {
 unsigned char i; 
 for (i=0;i<3;i++)
   {
   led_buff[i]=seg_table[temp%10];/*temp%10求余数‘假设一个数是234那么234/10=23余4也就是查找4的段码*/
   
   temp=temp/10;// 234/10=23因为不处理小数实际就等于右移了
   }
   
 }
/***************************************************************

主程序

***************************************************************/
 void main(void)
 {
 unsigned char i;
 unsigned int  k;
 unsigned int adc_old;
 unsigned long adc_ol;
 unsigned int adc_o;
 DDRD=0xff;
 PORTD=0xf0;
 OSCCAL=osccal;
 TIMSK = 0x40; //timer interrupt sources
 adc_mux=0;
 adc_init();
 timer1_init();
 pidcalc_init();
 SEI();
 for(i=0;i<3;i++)
   led_buff[i]=seg_table[8];
 for(i=0;i<200;i++)
   timer2_init();
   adc_old=0;
   adc_rel=0;
  while(1)
     {
		if(adc_old!=adc_rel)//ADC更新完毕就执行数据处理
	         {
		      adc_old=adc_rel;
			  pidcalc();
			  pidcalc_zizheng();
			    if(k<5) 
				    {
					k++;
					adc_ol+=adc_old;
					}
				else
				    {
					adc_o=adc_ol/5;
					adc_ol=0;
					k=0;
					}	
			  }  
	    ADCtoBCD(adc_o);  
	 }
 }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -