📄 digitaldcpower.c
字号:
/********************************************
**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 + -