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

📄 main.c

📁 本程序为编码器调节电压,能校对:输出电压,输入电压,与校对调节输出的电压值,适合做通用数字电源程序
💻 C
字号:
/*eeprom_is_ready() //EEPROM 忙检测(返回EEWE 位)
eeprom_busy_wait() //查询等待EEPROM 准备就绪
uint8_t eeprom_read_byte (const uint8_t *addr) //从指定地址读一字节
uint16_t eeprom_read_word (const uint16_t *addr) //从指定地址一字
void eeprom_read_block (void *buf, const void *addr, size_t n) //读块
void eeprom_write_byte (uint8_t *addr, uint8_t val) //写一字节至指定地址
void eeprom_write_word (uint16_t *addr, uint16_t val) //写一字到指定地址
void eeprom_write_block (const void *buf, void *addr, size_t n)//写块*/
/*
SIG_INTERRUPT0 外部中断INT0
SIG_INTERRUPT1 外部中断INT1
SIG_OUTPUT_COMPARE2 定时器/计数器比较匹配中断
SIG_OVERFLOW2 定时器/计数器2 溢出中断
SIG_INPUT_CAPTURE1 定时器/计数器2 输入捕获中断
SIG_OUTPUT_COMPARE1A 定时器/计数器1 比较匹配A
SIG_OUTPUT_COMPARE1B 定时器/计数器1 比较匹配B
SIG_OVERFLOW1 定时器/计数器1 溢出中断
SIG_OVERFLOW0 定时器/计数器0 溢出中断
SIG_SPI SPI 操作完成中断
SIG_UART_RECV USART 接收完成
SIG_UART_DATA USART 寄存器空
SIG_UART_TRANS USART 发送完成
SIG_ADC ADC转换完成
SIG_EEPROM_READY E2PROM 准备就绪
SIG_COMPARATOR 模拟比较器中断
SIG_2WIRE_SERIAL TWI 中断
SIG_SPM_READY 写程序存储器准备好
*/

/*
本程序为编码器调节电压,能校对:输出电压,输入电压,与校对调节输出的电压值,

同时按下FUN与SET会进去校对,
本程序给出了一个简单的应用,其实可能用在任何电源上,只要你的电源有一个PWM输出调节就行,因为它有校对功能嘛

   输出电压校对:Vo_xiao
     先用万用表测到输入电压,然后把这电压值输进程序(通过编码器调节)然后按SET键,校对完成.

   输入电压校对:Vi_xiao
     与输出电压校对方法一样,

   调节输出的电压值:PO_xiao(配合输出电压显示校对,校之前先把输出电压显示校好)
     L_X为下限电压校对,不般不怎么校,只要调编码器输出为0V就行,除非你的电源有负电压 VO 为你调节的电压输入值,由机内输入电压采集
     L_H 为上限电压校对,可以在任意点电压值上校对,程序会自动算出最高电压上限值,比如,你用5V来校对,调整VO显示到5V 这时按SET键,就校对完成了.

E_mail : veryjc@gmail.com
 
*/
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#define PWM_our  OCR1A
#define PWM      OCR1B
#include "lcdinf.c"
#define V_max 300
#define di    di1=10;
#define DLD di1=20;di2=60;di3=20
#define DIH   PORTD|=0x80
#define DIL   PORTD&=0x7f
#define key_in  (~PINA)
uch di1,di2,di3;
uch tep2;
uch ks,ks2;
#define set  0x80
#define fun  0x40
//参数的地址
#define vihas 0
#define vohas 2
#define volas 4
#define pohas 6
#define polas 8
#define poas 10
char *ch_sp;
uch ch_x;
uch ch_s=1;
uch key;//按键;
uch int_;//编码
uch up;//加十标志
uch make;
unsigned long power;//输出电压值
uint power_max;//当前最大电压设置
uint vi;//输出电压
uint vo;//输出电压值
uint va;//输出电流值
uint vi2;//输出电压
uint vo2;//输出电压值
uint va2;//输出电流值
uint adc_1,adc_2,adc_3;
uint vo_a[10];//三个变量的数组
uint vi_a[10];
uint va_a[10];

uint vi_kh;//每能道的修正系数

uint vo_kh;
uint vo_kl;

uint po_kh;
uint po_kl;
//----------------------
uch xiao;

uint adc_maxmin(uint *xp,uch _tep){
unsigned char i;
int ret;
int ret_tep;
unsigned char max_id,min_id,max_value,min_value;
ret=0;
for(i=1;i<10;i++)
ret+=*(xp+i);
//找到最大和最小值索引
ret/=10;
max_id=min_id=1;
max_value=min_value=0;
for(i=1;i<10;i++)
{
if(*(xp+i)>ret)
{
if(*(xp+i)-ret>max_value)
{
max_value=*(xp+i)-ret;
max_id=i;
}
}
else
{
if(ret-*(xp+i)>min_value)
{
min_value=ret-*(xp+i);
min_id=i;
}
}
}
//去掉第一个和最大最小值后的平均值
ret=0;
for(i=1;i<10;i++)
{
if((i!=min_id)&&(i!=max_id))
ret+=*(xp+i);
}
if(min_id!=max_id)
ret/=7;
else
ret/=8;
return ret; 
}
void adc_sy(void){
static uch  x,y;
if(x>10){
x=0;
	if(y<10){
	vo_a[y]=adc_1;
	vi_a[y]=adc_2;
	va_a[y]=adc_3;
	 y++;
	 }
	 else y=0;
	 }
	 else x++;
if(y==10){
	vo2=adc_maxmin(vo_a,1);
	vi2=adc_maxmin(vi_a,2);
	va2=adc_maxmin(va_a,3);
    y=0;
} 
	 }

SIGNAL(SIG_ADC)
{
if(ADMUX==0xC0){ADMUX=0xC1;adc_1=ADC;return;}
if(ADMUX==0xC1){ADMUX=0xC0;adc_2=ADC;return;}
//if(ADMUX==0xC2){ADMUX=0xC0;adc_3=ADC;return;}
}
SIGNAL(SIG_OVERFLOW0) 
{

 ADCSRA|=_BV(ADSC);
 uch tep;
 tep=key_in&0xc0;
 ks2=tep;
 xiao=tep;
if(tep){
	if(ks==10){tep2=tep;ks++;}
	 else ks++;
	}
else{ks=0;if(tep2){key=tep2;make=1;}tep2=0;}

  if(ch_s){
              w_by(*ch_sp);ch_s=0;
              if(ch_x<15){ch_x++;ch_sp++;}
               else {ch_x=0;ch_sp=&xy_ch;}
            }
else {xini(ch_x);ch_s=1;}

 if(di1){DIL;di1--;}//第一次响
  else {
    if(di2){di2--;DIH;}//第二次延时
	  else {if(di3){di3--;DIL;}else DIH;}//第三次响
	  }
 TCNT0=250;//20MS
  // power++;
}
uch s_up;
uch s_down;
SIGNAL(SIG_INTERRUPT0){
make=1;
if((PIND&0x0c)==0x0c)return;
if(s_down){s_down=0;return;}
 s_up=1;
 int_=1;
}
SIGNAL(SIG_INTERRUPT1){
make=1;//有修改
if((PIND&0x0c)==0x0c)return;
if(s_up){s_up=0;return;}
 s_down=1;
 int_=2;
}

void daly(void){
  uch x,y;
    for(x=100;x!=0;x--);
    for(y=250;y!=0;y--)for(x=250;x!=0;x--);
	}

void ini(void){
  
    PORTD=0xff;
	PORTB=0xff;
	DDRB=0xff;
	DDRC=0xff;
	DDRA=0x0;
	DDRD=0xf0;
daly();
    cli();
	c_b(ASSR,AS2);
	s_b(MCUCSR,JTD);s_b(MCUCSR,JTD);//关闭JTAG
    ADMUX=0xC0;//选择第七通道换转
	ADCSRA=_BV(ADEN)|_BV(ADSC)|_BV(ADPS0)|_BV(ADSC)|_BV(ADIE);

	GICR=0xc0;//设置中断
	MCUCR=0x0f;
	
	TCCR0=(1<<CS02)|(1<<CS00);
	TCCR1A=(1<<WGM11)|0xa0;
	TCCR1B=(1<<WGM13)|(1<<CS10);//
	ICR1=2000;
	lcdini();
	ch_sp=&xy_ch;
	ch_x=0;
	xini(0);
	dlay(80);
	TCNT0=220;
	
	
	TIMSK=(1<<TOIE0);
	sei();
	
  }
  uch dip;//小数点
  uch shu_z;//符号
  uch _shu[6];
  void shu_f(int x){
  uint tep;
    if(x<0){shu_z=1;x=~x+1;}
	_shu[3]=x/1000;
	tep=x%1000;
	_shu[2]=tep/100;
	x=tep%100;
	_shu[1]=x/10;
    _shu[0]=x%10; 
	}
  void di_OA(int x,uch a){//下行显示电流
   shu_f(x);
   xy_ch[a][0]='V';
   xy_ch[a][1]='A';
   xy_ch[a][2]=':';
   xy_ch[a][3]=ascii_s(_shu[2]);
    xy_ch[a][4]='.';
   xy_ch[a][5]=ascii_s(_shu[1]);
   xy_ch[a][6]=ascii_s(_shu[0]);
   xy_ch[a][7]='A';
  }
  void di_VI(int x,uch a){//下行显示输入电压
   shu_f(x);
   xy_ch[a][0]='V';
   xy_ch[a][1]='I';
   xy_ch[a][2]=':';
   xy_ch[a][3]=ascii_s(_shu[2]);
   xy_ch[a][4]=ascii_s(_shu[1]);
   xy_ch[a][5]='.';
   xy_ch[a][6]=ascii_s(_shu[0]);
   xy_ch[a][7]='V';
  }
  void di_Vo(int x,uch a){//下行显示输出电压
   shu_f(x);
   xy_ch[a][0]='V';
   xy_ch[a][1]='o';
   xy_ch[a][2]=':';
   xy_ch[a][3]=ascii_s(_shu[2]);
   xy_ch[a][4]=ascii_s(_shu[1]);
   xy_ch[a][5]='.';
   xy_ch[a][6]=ascii_s(_shu[0]);
   xy_ch[a][7]='V';
  }
  void di_Vout(int x,uch a){//下行显示输入电压
   shu_f(x);
   xy_ch[a][0]='V';
   xy_ch[a][1]='O';
   xy_ch[a][2]=':';
   xy_ch[a][3]=ascii_s(_shu[2]);
   xy_ch[a][4]=ascii_s(_shu[1]);
   xy_ch[a][5]='.';
   xy_ch[a][6]=ascii_s(_shu[0]);
   if(up)xy_ch[0][7]='V';
     else xy_ch[0][7]='+';
  }
   void di_AD(int x,uch a){//下行显示输入电压
   shu_f(x);
   xy_ch[a][0]='A';
   xy_ch[a][1]='D';
   xy_ch[a][2]=':';
   xy_ch[a][3]='!';
   xy_ch[a][4]=ascii_s(_shu[3]);
   xy_ch[a][5]=ascii_s(_shu[2]);
   xy_ch[a][6]=ascii_s(_shu[1]);
   xy_ch[a][7]=ascii_s(_shu[0]);
  }
  

  /*---------------量程式转换数学模型号--------------*/
int moxin(int ouh,int oul,int inh,int inl,int x){
 //inx为转换前的量程式,oux为转换后的量程,x为转换前的变化值
 //数学模型返回值=(ouh-oul)*(x-inl)/(inh-inl)+oul
 long y;
 long x1,x2,x3;
 x1=ouh-oul;
 x2=x-inl;
 x3=inh-inl;
 y=x1*x2;
 y=y/x3+oul;
 return (int)y;
 }

void vi_xiao(void){//输入电压校对
 uint tep_vi;
 tep_vi=vi;
 uint tep1;
 long x1,x2,x3;
 while(1){
 adc_sy();
 di_VI(tep_vi,0);
 di_AD(vi2,1);//430

   if(int_==1){if(tep_vi<V_max)tep_vi++;int_=0;}
   if(int_==2){if(tep_vi>0)tep_vi--;int_=0;}
   if(key==set)
   {
   key=0;
    tep1= moxin(1024,0,V_max,0,tep_vi);//值对应电压值
	x1=tep1;
	x2=vi2;
    x3=1024*x2/x1;
	vi_kh=(unsigned int)x3;
    eeprom_write_word(vihas,vi_kh);
	tep1= moxin(1024,0,vi_kh,0,vi2);
	vi= moxin(V_max,0,1024,0,tep1);
	
	di_VI(vi,1);
	daly();daly();daly();
	daly();daly();daly();
	daly();daly();daly();
	daly();daly();daly();
	daly();daly();daly();
   }
   if(key==fun){key=0;return;}
   
   
 }
 }
 void vo_xiao(void){//输入电压校对
 
uint tep_vo;
 tep_vo=vo;
 uint tep1;
 long x1,x2,x3;
 PWM_our=300;
 while(1){
 adc_sy();
 di_Vo(tep_vo,0);
 di_AD(vo2,1);//430

   if(int_==1){if(tep_vo<V_max)tep_vo++;int_=0;}
   if(int_==2){if(tep_vo>0)tep_vo--;int_=0;}
   if(key==set)
   {
   key=0;
    tep1= moxin(1024,0,V_max,0,tep_vo);//值对应电压值
	x1=tep1;
	x2=vo2;
    x3=1024*x2/x1;
	vo_kh=x3;
    eeprom_write_word(vohas,vo_kh);
	tep1= moxin(1024,0,vo_kh,0,vo2);
	vo= moxin(V_max,0,1024,0,tep1);
	
	di_Vo(vo,1);
	daly();daly();daly();
	daly();daly();daly();
	daly();daly();daly();
	daly();daly();daly();
	daly();daly();daly();
   }
   if(key==fun){key=0;return;}
 }
 }
  void po_xiao(void){//输入电压校对
  uint mo_tep;
  uch out_s;
  uint po_tep;
 
  out_s=1;
  PWM_our=po_kl;
  
  while(1){
   
   
   shu_f(PWM_our);
   xy_ch[0][1]='_';
   xy_ch[0][2]='X';
   xy_ch[0][3]=' ';
   xy_ch[0][4]=ascii_s(_shu[3]);
   xy_ch[0][5]=ascii_s(_shu[2]);
   xy_ch[0][6]=ascii_s(_shu[1]);
   xy_ch[0][7]=ascii_s(_shu[0]);
  if(out_s==1){
     xy_ch[0][0]='L';

     if(key==set){
	 out_s=0;
     key=0;
	 po_kl=PWM_our;
	
     eeprom_write_word(polas,po_kl);
	di_AD(po_kl,0);
	daly();daly();daly();
	daly();daly();daly();
	daly();daly();daly();
	daly();daly();daly();
	daly();daly();daly();
	PWM_our=666;
	 }
 }
	else {
	xy_ch[0][0]='H';
    if(key==set){out_s=1;
     key=0; 
     po_tep=moxin(2000,0,V_max,0,vo);
	 po_kh=moxin(2000,0,PWM_our,po_kl,po_tep);
	 
    eeprom_write_word(pohas,po_kh);
	di_AD(po_kh,0);;
	daly();daly();daly();
	daly();daly();daly();
	daly();daly();daly();
	daly();daly();daly();
	daly();daly();daly();
	PWM_our=po_kl;
      }
 
 }
      adc_sy();
	  mo_tep= moxin(1024,0,vo_kh,0,vo2);
	  vo= moxin(V_max,0,1024,0,mo_tep);
	  di_Vo(vo,1);
   if(int_==1){if(PWM_our<2000)PWM_our++;int_=0;}
   if(int_==2){if(PWM_our>0)PWM_our--;int_=0;}
   
   if(key==fun){key=0;return;}
 }
 }
 char xiao_chs[][8]={//上行
                       {"Vi_Xiao ",},
					   {"Vo_Xiao ",},
					   {"PO_Xiao ",},
					   };
					   
  void pwxd(void){//校对
  uch tep;
  uch cs_fun;
   xy_ch[0][0]='X';
   xy_ch[0][1]='i';
   xy_ch[0][2]='a';
   xy_ch[0][3]='o';
   xy_ch[0][4]=' ';
   xy_ch[0][5]='D';
   xy_ch[0][6]='u';
   xy_ch[0][7]='i';
   xy_ch[1][0]=' ';
   xy_ch[1][1]=' ';
   xy_ch[1][2]=' ';
   xy_ch[1][3]=' ';
   xy_ch[1][4]=' ';
   xy_ch[1][5]=' ';
   xy_ch[1][6]=' ';
   xy_ch[1][7]=' ';
   st:
   if(key==0)goto st;
   daly();
   key=0;
   cs_fun=0;
   tep=0;
   while(1){
   if(tep){
   
   if(int_==1){if(cs_fun<2)cs_fun++;int_=0;}
   if(int_==2){if(cs_fun>0)cs_fun--;int_=0;}
   dis_chs(&xiao_chs[cs_fun],0);
   dis_chs("OK?_SET ",1);
   if(key==set){
     key=0;
	 if(cs_fun==0)vi_xiao();
	 if(cs_fun==1)vo_xiao();
     if(cs_fun==2)po_xiao();
	 }
   }
   else{
   
   xy_ch[1][0]='O';
   xy_ch[1][1]='K';
   xy_ch[1][2]='?';
   xy_ch[1][3]=' ';
   xy_ch[1][4]=' ';
   xy_ch[1][5]=' ';
   xy_ch[1][6]=' ';
   xy_ch[1][7]=' ';
   if(key==set){tep=1;key=0;}
   }
   
   if(key==fun){key=0;return;}
   }
   
  }
  int main(void){
  uint eep_daly;
  uch cs;//下行显示模试
  uch y;
  uint pwm_tep;
  unsigned long pwm_tep_s;
  uint temp;
  uint mo_tep;
    ini();
 power_max=V_max;
 up=1;
 cs=0;
 //读取修正系数
 
  vi_kh=eeprom_read_word(vihas);
  vo_kh=eeprom_read_word(vohas);
  vo_kl=eeprom_read_word(volas);
  po_kh =eeprom_read_word(pohas);
  po_kl=eeprom_read_word(polas);
  power=eeprom_read_word(poas);
    if(vi_kh>1500){vi_kh=1024;eeprom_write_word(vihas,vi_kh);}
	  if(vo_kh>1500){vo_kh=1024;eeprom_write_word(vohas,vo_kh);}
	    if(vo_kl>1500){vo_kl=0;eeprom_write_word(volas,vo_kl);}
		  if(po_kh>2000){po_kh=2000;eeprom_write_word(pohas,po_kh);}
		    if(po_kl>2000){po_kl=0;eeprom_write_word(polas,po_kl);}
			  if(power>300){power=0;eeprom_write_word(poas,power);}
 // vi_kh=1000;
 DLD;
  while(1){
  if(make){make=0;di;
  eep_daly=0;
  }
  if(eep_daly>8000){eeprom_write_word(poas,power);}//累积到8000时保存POWER值
  else eep_daly++;
  
  
  
  
  pwm_tep_s=power*2000/V_max;
  PWM_our=moxin(2000,0,po_kh,0,pwm_tep_s);
  //PWM_our=pwm_tep_s;
  
 /*
  if(pwm_tep!=pwm_tep_s){
      if(pwm_tep<pwm_tep_s)pwm_tep+=1;
	       else pwm_tep-=1;
		   }
	*/	   
  if(key==set){if(up)up=0;else up=1;key=0;}
  if(key==fun){if(cs<1)cs++;else cs=0;key=0;}
  if(int_==1){if(power<(vi-5))if(up)power++;else power+=10;if(power>(vi-5))power=(vi-5);int_=0;}
   if(int_==2){if(power>0)if(up)power--;else power-=10;if(power>(vi-5))power=0;int_=0;}
  if(xiao==0xc0){if(temp<500)temp++;else {di1=200;key=0;pwxd();}}else temp=0;
     di_Vout(power,0);
	 	 
	  mo_tep= moxin(1024,0,vi_kh,0,vi2);
	  vi= moxin(V_max,0,1024,0,mo_tep);
	 switch (cs)
	 {
	  case 0 : 
	  
	  di_VI(vi,1);
	  break;
	 
	  case 1 : 
	  mo_tep= moxin(1024,0,vo_kh,0,vo2);
	  vo= moxin(V_max,0,1024,0,mo_tep);
	  di_Vo(vo,1);break;
	  default :break;
	  }
adc_sy();
  }
  }
 
  

⌨️ 快捷键说明

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