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

📄 digitaldcpower.c

📁 多通道电压表数模转换
💻 C
📖 第 1 页 / 共 2 页
字号:
/********************************************
**Designed by GandF 
********************************************/
#include <iom8v.h>
#include <macros.h>
#include <MATH.H>
#include <STRING.H>
#include <stdlib.h>
#include <eeprom.h>
#include "lcd.h"
#include "delay.h"
#include "datatran.h"

#define   Fosc           4096000          //系统晶振频率 4.096MHz 
#define   Fosc_TIME2      (64*10)   	  //TIME2 比较中断频率=采样率*AD通道数*工频50Hz的倍数

#define  ATX_CTL_PORT 	 PORTC            //ATX电源控制端
#define  ATX_CTL_PIN 	 PINC             //ATX电源控制端
#define  ATX_CTL_DDR  	 DDRC             //ATX电源控制端
#define  ATX_CTL   	     PC4              //ATX电源控制端

#pragma data:eeprom 
unsigned char EEPROM_temp[]={'D','e','s','i','g','n',' ','b','y',' ','C','H','Q'};
unsigned int  Dead_count=10000;
unsigned int  uiEEPROM_Vref_preset=2665;         // 参考电压=2665mV
unsigned int  uiEEPROM_VtoPWM_preset[42]=        // PWM控制输出电压与TIME1 比较寄存器OCR的关系值
                 { 
				   0,100,200,300,400,500,600,700,800,900,// 添加校正数据
				   1000,1100,1200,1300,1400,1500,1600,1700,1800,1900,
				   2000,2100,2200,2300,2400,2500,2600,2700,2800,2900,
				   3000,3100,3200,3300,3400,3500,3600,3700,3800,3900,
				   4000,4100
				 };			
unsigned int  uiEEPROM_ItoPWM_preset[42]=        // PWM控制输出电流与TIME1 比较寄存器OCR的关系值
                 { 
				   0,100,200,300,400,500,600,700,800,900,// 添加校正数据
				   1000,1100,1200,1300,1400,1500,1600,1700,1800,1900,
				   2000,2100,2200,2300,2400,2500,2600,2700,2800,2900,
				   3000,3100,3200,3300,3400,3500,3600,3700,3800,3900,
				   4000,4100
				 };				
 
#pragma data:data 

unsigned char  config=0x10,config_temp=0x10;              // 功能选择设定
unsigned char  num1,num2;                                 // 临时寄存器
unsigned int   uitemp1,uitemp2;                           // 临时寄存器
unsigned char  time2_cmp_i=64;                            // TIME2 比较中断i=采样率*AD通道数
unsigned char  display_control=0x40;                      // LCD显示的定时控制字节

unsigned char  *s1="123456789012345678901",*s2;           // LCD显示的字符串
unsigned int   uiVout_set=0,uiIout_set=0;         		  // PWM A/B 通道(A通道控制电压,B通道控制电流)的电压设定输出值
unsigned int   uiadc_value_temp;                          // ADC中断的 采样值
unsigned int   uitime2_adc0_value_sum,uiadc0_value; 	  // TIME2  ADC0 16个采样值的加和值,电压输出值=Vref*uitime2_adc0_value_sum/16/1024
unsigned int   uitime2_adc1_value_sum,uiadc1_value; 	  // TIME2  ADC1 16个采样值的加和值,电压输出值
unsigned int   uitime2_adc2_value_sum,uiadc2_value; 	  // TIME2  ADC2 16个采样值的加和值,电压输出值
unsigned int   uitime2_adc3_value_sum,uiadc3_value; 	  // TIME2  ADC3 16个采样值的加和值,电压输出值

unsigned long  uladc_data,uladc_data2,time2_count;   				  // ADC的转换数据, TIME2 中断计数N,0.1S计数(可作长时间定时器136年)

unsigned char  ucADC_select;   							  // 四通道AD选择
unsigned int   uiADC_value_sum[4]; 						  // 四通道AD,64个数据加和值

unsigned int   uiVref_preset;         				      // 参考电压=2665mV
unsigned int   uiVtoPWM_preset[42];        				  // PWM控制输出电压与TIME1 比较寄存器OCR的关系值			
unsigned int   uiItoPWM_preset[42];
				 
void main(void)
  {
	 WDR();
	 watchdog_init();
	 init_devices();
	 CLI();                     // disable all interrupts
	 timer1_init();             // 使能PWM
	 adc_init();                // 使能ADC
	 timer2_init();             // 使能AD转换
	 delay_ms(1000);
	 WDR();
	 EEPROM_READ((int) &Dead_count,uitemp1);  // 开机次数计数
	 uint_to_ascii(uitemp1,s1);
	 uitemp1 --;
	 //uitemp1 = 10000;
	 EEPROM_WRITE((int) &Dead_count,uitemp1);
	 lcd_init(); 
	 lcd_write_string(0,0,"hello!");
	 SEI();                    // re-enable interrupts
	 lcd_write_string(0,1,s1);
	 delay_ms(500);
	 lcd_init();                // LCD 初始化
	 lcd_write_string(0,0,"Good Luck!");
	 lcd_write_string(0,1,"V1.00 2005.11.13.ADC4");
	 delay_ms(500);
	 SRAM_data_init();          // 从EEPROM的数据设置SRAM
	 lcd_init();                // LCD 初始化
	 lcd_write_string(0,0,"Please");
	 lcd_write_string(0,1,"Select Program!");
	 delay_ms(500);
	 lcd_init();                // LCD 初始化
	 lcd_write_string(0,0,"Default Program= 0");
	 lcd_write_string(0,1,"Program =  DCpower");
	 delay_ms(500);
	 lcd_clear();
	 uart_init();
	 while(1)
       {
		 if(config != config_temp) program_set(); // config != config_temp 当前功能已退出,重新选择功能
		 program_select();
		 if((display_control & 0x40) == 0x40)  // 如果display_control 第8位为1,就显示
            {
	          display_control = display_control & 0x07; // display_control 第8位清零
	          DCpower_display();
            }
	   }
  } // *** main() end ***

/********由定时器T2中断启动 连续转换四个ADC通道的值 **********/
#pragma interrupt_handler adc_isr:15
void adc_isr(void)
{
 uiadc_value_temp  = ADCL;
 uiadc_value_temp |= (unsigned int)ADCH << 8;
 SEI();
 switch(ucADC_select)
   {
	 case  0 :    // ADC0通道 数据处理
	   {
		 ADMUX   = 0xc1;          // 切换到ADC1通道,内部Vref
         //ADMUX   = 0x01;        // 外部Vref,ADC1通道
		 uiADC_value_sum[ucADC_select] += uiadc_value_temp; //加和值
         ADCSRA |= (1<<ADSC);     // enable adc
		 ucADC_select ++ ;        // 切换到ADC1通道
		 break;
	   }
     case  1 :    // ADC1通道 数据处理
	   {
		 ADMUX   = 0xc2;          // 切换到ADC2通道,内部Vref
         //ADMUX   = 0x02;        // 外部Vref,ADC2通道
		 uiADC_value_sum[ucADC_select] += uiadc_value_temp; //加和值 
		 ADCSRA |= (1<<ADSC);     // enable adc
		 ucADC_select ++ ;        // 切换到ADC2通道
		 break;
	   }
     case  2 :    // ADC2通道 数据处理
	   {
		 ADMUX   = 0xc3;          // 切换到ADC3通道,内部Vref
         //ADMUX   = 0x03;        // 外部Vref,ADC3通道
		 uiADC_value_sum[ucADC_select] += uiadc_value_temp; //加和值 
         ADCSRA |= (1<<ADSC);     // enable adc
		 ucADC_select ++ ;        // 切换到ADC3通道
		 break;
	   }
     case  3 :    // ADC3通道 数据处理
	   {
		 ADMUX   = 0xc0;          // 切换到ADC0通道,内部Vref,但不启动,等待定时器T2启动
         //ADMUX   = 0x00;        // 外部Vref,ADC0通道
		 uiADC_value_sum[ucADC_select] += uiadc_value_temp; //加和值 
		 ucADC_select = 0 ;       // 切换到ADC0通道,但不启动,等待定时器T2启动
		 break;
	   }
	 default : 
	   {
	    ADMUX   = 0xc0;          // 切换到ADC0通道,内部Vref,但不启动,等待定时器T2启动
	    ucADC_select = 0 ;       // 切换到ADC0通道,但不启动,等待定时器T2启动
	    break;
	   }
   } // switch end
} // AD中断处理 end
/********由定时器T2中断启动 连续转换四个ADC通道的值 ****** end */

/******定时器T2中断*****************************
*1、喂狗;2、启动ADC;
*3、将ADC的加和值平均,计算电压值
************************************************/
#pragma interrupt_handler timer2_comp_isr:4
void timer2_comp_isr(void)                         // TIME2做四通道ADC0、ADC1、ADC2、ADC3的积分滤波 10Hz,16采样率
  {
   WDR();   //喂狗
   if((time2_cmp_i & 0x03) == 0x00) ADCSRA |= (1<<ADSC);  // 启动ADC,16次采样率
   time2_cmp_i --;
   if(time2_cmp_i == 0)
    {
	  uitime2_adc0_value_sum = uiADC_value_sum[0]; // 16个数据加和值
	  uiADC_value_sum[0] = 0;                      // 清零
	  uitime2_adc1_value_sum = uiADC_value_sum[1]; // 16个数据加和值
	  uiADC_value_sum[1] = 0;                      // 清零
	  uitime2_adc2_value_sum = uiADC_value_sum[2]; // 16个数据加和值
	  uiADC_value_sum[2] = 0;                      // 清零
	  uitime2_adc3_value_sum = uiADC_value_sum[3]; // 16个数据加和值
	  uiADC_value_sum[3] = 0;                      // 清零
	  time2_cmp_i = 64;
      SEI();
	  time2_count ++;                              // 0.1S计数
	  display_control ++;                    
	  if((display_control & 0x07) == 5) display_control = 0x40;       // display_control 计数为5时,第7位置1
	}
  }
//******定时器T2中断************************* end */


void SRAM_data_init(void)       /*从EEPROM读入SRAM区*/
  {
   unsigned char i;
   EEPROM_READ((int) &uiEEPROM_Vref_preset,uiVref_preset);   // 参考电压值
   
   for(i=0;i<42;i++)             // PWM控制输出电压与TIME1 比较寄存器OCR的校正值
     {
	  EEPROM_READ((int) &uiEEPROM_VtoPWM_preset[i],uiVtoPWM_preset[i]);
	 }
   for(i=0;i<42;i++)             // PWM控制输出电流与TIME1 比较寄存器OCR的校正值
     {
	  EEPROM_READ((int) &uiEEPROM_ItoPWM_preset[i],uiItoPWM_preset[i]);
	 }
  }	
  
void EEPROM_Vout_preset_write(void)     /*PWM控制输出电压与TIME1 比较寄存器OCR的校正值写入EEPROM区*/
  {
    unsigned char i;
	for(i=0;i<42;i++)            // PWM控制输出电压与TIME1 比较寄存器OCR的校正值
     {
	  EEPROM_WRITE((int) &uiEEPROM_VtoPWM_preset[i],uiVtoPWM_preset[i]);
	 }
  }
void EEPROM_Iout_preset_write(void)     /*PWM控制输出电流与TIME1 比较寄存器OCR的校正值写入EEPROM区*/
  {
    unsigned char i;
	for(i=0;i<42;i++)            // PWM控制输出电流与TIME1 比较寄存器OCR的校正值
     {
	  EEPROM_WRITE((int) &uiEEPROM_ItoPWM_preset[i],uiItoPWM_preset[i]);
	 }
  } 
   			 
unsigned int  PWM_Vout_to_count(unsigned int   uiVout_set)  // 将设定的电压值修正转换成PWM(TIME1)的比较寄存器OCR的值,uiVout_set=0-4094
  {
    unsigned char i;
	unsigned int  PWM_count;
	i = uiVout_set/100;
	PWM_count = uiVtoPWM_preset[i]+(uiVtoPWM_preset[i+1]-uiVtoPWM_preset[i])*(uiVout_set%100)/100; // 插值法
	if(PWM_count < 1) PWM_count = 1;                            // PWM返回值范围为1-4094
	if(PWM_count > 4094) PWM_count = 4094;
	return PWM_count;
  }

unsigned int  PWM_Iout_to_count(unsigned int   uiIout_set)  // 将设定的电压值修正转换成PWM(TIME1)的比较寄存器OCR的值,uiVout_set=0-4094
  {
    unsigned char i;
	unsigned int  PWM_count;
	i = uiIout_set/100;
	PWM_count = uiItoPWM_preset[i]+(uiItoPWM_preset[i+1]-uiItoPWM_preset[i])*(uiIout_set%100)/100; // 插值法
	if(PWM_count < 1) PWM_count = 1;                            // PWM返回值范围为1-4094
	if(PWM_count > 4094) PWM_count = 4094;
	return PWM_count;
  }


void port_init(void)
{
 DDRB  = 0x00;
 PORTB = 0x00;
 DDRC  = 0x00;
 PORTC = 0x00; //m103 output only
 DDRD  = 0x00;
 PORTD = 0x00;
}

// *********** ADC的设定及函数****************
//ADC initialize
// Conversion time: 128KHz(系统位4.096MHz,32分频)
void adc_init(void)
 {
  ADCSRA= 0x00;       //disable adc
  ACSR  = (1<<ACD);   //disable comparator
  ADMUX = 0xc0;       //内部Vref,ADC0通道
  //ADMUX = 0x00;       //外部Vref,ADC0通道
  ADCSRA= (1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS0);   // enable adc,中断允许,32分频|(1<<ADSC)
  //ADCSRA= (1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1);   //enable adc,64分频
  //ADCSRA= (1<<ADEN)|(1<<ADSC)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);//enable adc,128分频
 }
// *********** ADC的设定及函数**************end**

 
//TIMER2 initialize - prescale:1024
// WGM: CTC
// actual value: 32*2*10Hz (0.0%)=采样率*AD通道数*工频50Hz的倍数
void timer2_init(void)
  {
    TCCR2  = 0x00; 		   			   	 						  //stop
    ASSR   = 0x00; 				 	   	  						  //关闭异步方式
    TCNT2  = 0x00;							  					  //setup
    OCR2   = Fosc/Fosc_TIME2/256-1;		 	  		 			  //设置TIME2 比较中断频率
    TCCR2  = (1<<WGM21)|(1<<CS22)|(1<<CS21); 					  //CTC模式,内部时钟256分频
    TIMSK |= (1<<OCIE2); 					  					  //timer2 中断允许
  }

//TIMER1 initialize - prescale:1
// WGM: 14) PWM fast, TOP=ICRn
// desired value: 2000Hz
// actual value: 2000.000Hz (0.0%)
void timer1_init(void)
  {
   DDRB  |= (1<<PB1);        //设置OC1A-PB1为输出
   DDRB  |= (1<<PB2);        //设置OC1B-PB2为输出
   TCCR1B = 0x00; //stop
   TCNT1H = 0x00; //setup
   TCNT1L = 0x00;
   OCR1A  = PWM_Vout_to_count(uiVout_set);
   OCR1B  = PWM_Iout_to_count(uiIout_set);
   ICR1H  = 0x0F;          // 12位PWM
   ICR1L  = 0xFF;
   TCCR1A = (1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0)|(1<<WGM11);    //0xF2;比较匹配置位OC1A/B
   TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS10);       //0x19; WGM: 14) PWM fast, TOP=ICRn;内部时钟1分频//start Timer
  }

unsigned int cal_VD(unsigned int uiAD_16sum_data)
  {
	uladc_data = uiAD_16sum_data;
	return ((unsigned int)((uladc_data*uiVref_preset)>>14));    // 输出ADC0的电压值VD0=Vref*uitime2_adc0_value_sum/16/1024
  }
  
//Watchdog initialize
// prescale: 2048K
void watchdog_init(void)
{
 WDR(); //this prevents a timout on enabling
 WDTCR = 0x1F; //WATCHDOG ENABLED - dont forget to issue WDRs
 WDTCR = 0x0F; //WATCHDOG ENABLED - 看门狗定时器预分频设为2048K,2.1S
 WDR();
}

void init_devices(void)
  {
   //stop errant interrupts until set up
	 port_init();
	 MCUCR = 0x00;
     GICR  = 0x00;
     TIMSK = 0x00; //timer interrupt sources
   //all peripherals are now initialized
  }
  
//********** ADC显示  *************
void DCpower_display(void)  
  {
		 lcd_write_string(0,0,"D0=    mV  D1=    mV");  // LCD显示格式
		 lcd_write_string(0,1,"D2=    mV  D3=    mV");
		 //uart输出ADC0的电压值
	     uiadc0_value=cal_VD(uitime2_adc0_value_sum);    // 输出ADC0的电压值VD0=Vref*uitime2_adc0_value_sum/16/1024
		 uint_to_ascii(uiadc0_value,s1);
		 putstring("D0=");                 // uart输出ADC0

⌨️ 快捷键说明

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