单片机教程网

电脑版
提示:原网页已由神马搜索转码, 内容由www.51hei.com提供.
查看:4353|回复:3
打印上一主题下一主题

ATMEGA8单片机数控电源和电压自动校正的C语言程序

[复制链接]
跳转到指定楼层
楼主
ID:696930发表于 2020-10-9 10:16|只看该作者|只看大图回帖奖励
先用ISP下载线把boot.hex写入M8.
FUSE设定为外部晶振(4.096MHz),启动硬件"看门狗",和BOOT区启动

附上M8用RS232接口在线升级的BOOT软件
使用:按下RESET键后按下S12键,就可以用AvrProg了。

电路原理图如下:


单片机源程序如下:
  1. /********************************************
  2. **Designed by GandF
  3. ********************************************/
  4. #include< iom8v.h>
  5. #include< macros.h>
  6. #include< MATH.H>
  7. #include< STRING.H>
  8. #include< stdlib.h>
  9. #include< eeprom.h>
  10. #include "lcd.h"
  11. #include "delay.h"
  12. #include "datatran.h"

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

  15. #define  ATX_CTL_PORT       PORTC         //ATX电源控制端
  16. #define  ATX_CTL_PIN       PINC         //ATX电源控制端
  17. #define  ATX_CTL_DDR         DDRC         //ATX电源控制端
  18. #define  ATX_CTL           PC4           //ATX电源控制端

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

  39. #pragma data:data

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

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

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

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

  55. unsigned int   uiVref_preset;                           // 参考电压=2665mV
  56. unsigned int   uiVtoPWM_preset[42];                         // PWM控制输出电压与TIME1 比较寄存器OCR的关系值            
  57. unsigned int   uiItoPWM_preset[42];
  58.                   
  59. void main(void)
  60.   {
  61.        WDR();
  62.        watchdog_init();
  63.        init_devices();
  64.        CLI();               // disable all interrupts
  65.        timer1_init();         // 使能PWM
  66.        adc_init();           // 使能ADC
  67.        timer2_init();         // 使能AD转换
  68.        delay_ms(1000);
  69.        WDR();
  70.        EEPROM_READ((int)& Dead_count,uitemp1);  // 开机次数计数
  71.        uint_to_ascii(uitemp1,s1);
  72.        uitemp1 --;
  73.        //uitemp1 = 10000;
  74.        EEPROM_WRITE((int)& Dead_count,uitemp1);
  75.        lcd_init();
  76.        lcd_write_string(0,0,"hello!");
  77.        SEI();               // re-enable interrupts
  78.        lcd_write_string(0,1,s1);
  79.        delay_ms(500);
  80.        lcd_init();           // LCD 初始化
  81.        lcd_write_string(0,0,"Good Luck!");
  82.        lcd_write_string(0,1,"V1.00 2005.11.13.ADC4");
  83.        delay_ms(500);
  84.        SRAM_data_init();       // 从EEPROM的数据设置SRAM
  85.        lcd_init();           // LCD 初始化
  86.        lcd_write_string(0,0,"Please");
  87.        lcd_write_string(0,1,"Select Program!");
  88.        delay_ms(500);
  89.        lcd_init();           // LCD 初始化
  90.        lcd_write_string(0,0,"Default Program= 0");
  91.        lcd_write_string(0,1,"Program =  DCpower");
  92.        delay_ms(500);
  93.        lcd_clear();
  94.        uart_init();
  95.        while(1)
  96.      {
  97.            if(config != config_temp) program_set(); // config != config_temp 当前功能已退出,重新选择功能
  98.            program_select();
  99.            if((display_control& 0x40) == 0x40)  // 如果display_control 第8位为1,就显示
  100.          {
  101.              display_control = display_control& 0x07; // display_control 第8位清零
  102.              DCpower_display();
  103.          }
  104.        }
  105.   } // *** main() end ***

  106. /********由定时器T2中断启动 连续转换四个ADC通道的值 **********/
  107. #pragma interrupt_handler adc_isr:15
  108. void adc_isr(void)
  109. {
  110. uiadc_value_temp  = ADCL;
  111. uiadc_value_temp |= (unsigned int)ADCH<< 8;
  112. SEI();
  113. switch(ucADC_select)
  114.    {
  115.        case  0 :   // ADC0通道 数据处理
  116.        {
  117.            ADMUX   = 0xc1;       // 切换到ADC1通道,内部Vref
  118.        //ADMUX   = 0x01;       // 外部Vref,ADC1通道
  119.            uiADC_value_sum[ucADC_select] += uiadc_value_temp; //加和值
  120.        ADCSRA |= (1<<ADSC);     // enable adc
  121.            ucADC_select ++ ;       // 切换到ADC1通道
  122.            break;
  123.        }
  124.      case  1 :   // ADC1通道 数据处理
  125.        {
  126.            ADMUX   = 0xc2;       // 切换到ADC2通道,内部Vref
  127.        //ADMUX   = 0x02;       // 外部Vref,ADC2通道
  128.            uiADC_value_sum[ucADC_select] += uiadc_value_temp; //加和值
  129.            ADCSRA |= (1<<ADSC);     // enable adc
  130.            ucADC_select ++ ;       // 切换到ADC2通道
  131.            break;
  132.        }
  133.      case  2 :   // ADC2通道 数据处理
  134.        {
  135.            ADMUX   = 0xc3;       // 切换到ADC3通道,内部Vref
  136.        //ADMUX   = 0x03;       // 外部Vref,ADC3通道
  137.            uiADC_value_sum[ucADC_select] += uiadc_value_temp; //加和值
  138.        ADCSRA |= (1<<ADSC);     // enable adc
  139.            ucADC_select ++ ;       // 切换到ADC3通道
  140.            break;
  141.        }
  142.      case  3 :   // ADC3通道 数据处理
  143.        {
  144.            ADMUX   = 0xc0;       // 切换到ADC0通道,内部Vref,但不启动,等待定时器T2启动
  145.        //ADMUX   = 0x00;       // 外部Vref,ADC0通道
  146.            uiADC_value_sum[ucADC_select] += uiadc_value_temp; //加和值
  147.            ucADC_select = 0 ;     // 切换到ADC0通道,但不启动,等待定时器T2启动
  148.            break;
  149.        }
  150.        default :
  151.        {
  152.          ADMUX   = 0xc0;       // 切换到ADC0通道,内部Vref,但不启动,等待定时器T2启动
  153.          ucADC_select = 0 ;     // 切换到ADC0通道,但不启动,等待定时器T2启动
  154.          break;
  155.        }
  156.    } // switch end
  157. } // AD中断处理 end
  158. /********由定时器T2中断启动 连续转换四个ADC通道的值 ****** end */

  159. /******定时器T2中断*****************************
  160. *1、喂狗;2、启动ADC;
  161. *3、将ADC的加和值平均,计算电压值
  162. ************************************************/
  163. #pragma interrupt_handler timer2_comp_isr:4
  164. void timer2_comp_isr(void)                 // TIME2做四通道ADC0、ADC1、ADC2、ADC3的积分滤波 10Hz,16采样率
  165.   {
  166.    WDR();   //喂狗
  167.    if((time2_cmp_i& 0x03) == 0x00) ADCSRA |= (1<<ADSC);  // 启动ADC,16次采样率
  168.    time2_cmp_i --;
  169.    if(time2_cmp_i == 0)
  170.    {
  171.        uitime2_adc0_value_sum = uiADC_value_sum[0]; // 16个数据加和值
  172.        uiADC_value_sum[0] = 0;               // 清零
  173.        uitime2_adc1_value_sum = uiADC_value_sum[1]; // 16个数据加和值
  174.        uiADC_value_sum[1] = 0;               // 清零
  175.        uitime2_adc2_value_sum = uiADC_value_sum[2]; // 16个数据加和值
  176.        uiADC_value_sum[2] = 0;               // 清零
  177.        uitime2_adc3_value_sum = uiADC_value_sum[3]; // 16个数据加和值
  178.        uiADC_value_sum[3] = 0;               // 清零
  179.        time2_cmp_i = 64;
  180.      SEI();
  181.        time2_count ++;                     // 0.1S计数
  182.        display_control ++;              
  183.        if((display_control& 0x07) == 5) display_control = 0x40;     // display_control 计数为5时,第7位置1
  184.      }
  185.   }
  186. //******定时器T2中断************************* end */


  187. void SRAM_data_init(void)     /*从EEPROM读入SRAM区*/
  188.   {
  189.    unsigned char i;
  190.    EEPROM_READ((int)& uiEEPROM_Vref_preset,uiVref_preset);   // 参考电压值
  191.   
  192.    for(i=0;i<42;i++)         // PWM控制输出电压与TIME1 比较寄存器OCR的校正值
  193.      {
  194.        EEPROM_READ((int)& uiEEPROM_VtoPWM_preset[i],uiVtoPWM_preset[i]);
  195.        }
  196.    for(i=0;i<42;i++)         // PWM控制输出电流与TIME1 比较寄存器OCR的校正值
  197.      {
  198.        EEPROM_READ((int)& uiEEPROM_ItoPWM_preset[i],uiItoPWM_preset[i]);
  199.        }
  200.   }    
  201.   
  202. void EEPROM_Vout_preset_write(void)     /*PWM控制输出电压与TIME1 比较寄存器OCR的校正值写入EEPROM区*/
  203.   {
  204.    unsigned char i;
  205.      for(i=0;i<42;i++)         // PWM控制输出电压与TIME1 比较寄存器OCR的校正值
  206.      {
  207.        EEPROM_WRITE((int)& uiEEPROM_VtoPWM_preset[i],uiVtoPWM_preset[i]);
  208.        }
  209.   }
  210. void EEPROM_Iout_preset_write(void)     /*PWM控制输出电流与TIME1 比较寄存器OCR的校正值写入EEPROM区*/
  211.   {
  212.    unsigned char i;
  213.      for(i=0;i<42;i++)         // PWM控制输出电流与TIME1 比较寄存器OCR的校正值
  214.      {
  215.        EEPROM_WRITE((int)& uiEEPROM_ItoPWM_preset[i],uiItoPWM_preset[i]);
  216.        }
  217.   }
  218.                 
  219. unsigned int  PWM_Vout_to_count(unsigned int   uiVout_set)  // 将设定的电压值修正转换成PWM(TIME1)的比较寄存器OCR的值,uiVout_set=0-4094
  220.   {
  221.    unsigned char i;
  222.      unsigned int  PWM_count;
  223.      i = uiVout_set/100;
  224.      PWM_count = uiVtoPWM_preset[i]+(uiVtoPWM_preset[i+1]-uiVtoPWM_preset[i])*(uiVout_set%100)/100; // 插值法
  225.      if(PWM_count< 1) PWM_count = 1;                   // PWM返回值范围为1-4094
  226.      if(PWM_count > 4094) PWM_count = 4094;
  227.      return PWM_count;
  228.   }

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


  239. void port_init(void)
  240. {
  241. DDRB  = 0x00;
  242. PORTB = 0x00;
  243. DDRC  = 0x00;
  244. PORTC = 0x00; //m103 output only
  245. DDRD  = 0x00;
  246. PORTD = 0x00;
  247. }

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


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

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

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

  307. void init_devices(void)
  308.   {
  309.    //stop errant interrupts until set up
  310.        port_init();
  311.        MCUCR = 0x00;
  312.      GICR  = 0x00;
  313.      TIMSK = 0x00; //timer interrupt sources
  314.    //all peripherals are now initialized
  315.   }
  316.   
  317. //********** ADC显示  *************
  318. void DCpower_display(void)  
  319.   {
  320.            lcd_write_string(0,0,"D0=   mV  D1=   mV");  // LCD显示格式
  321.            lcd_write_string(0,1,"D2=   mV  D3=   mV");
  322.            //uart输出ADC0的电压值
  323.          uiadc0_value=cal_VD(uitime2_adc0_value_sum);   // 输出ADC0的电压值VD0=Vref*uitime2_adc0_value_sum/16/1024
  324.            uint_to_ascii(uiadc0_value,s1);
  325.            putstring("D0=");             // uart输出ADC0
  326.            putstring(s1);
  327.            putstring("mV ");
  328.            lcd_write_string(3,0,s1);       // LCD显示
  329.           
  330.            //uart输出ADC1的电压值
  331.          uiadc1_value=cal_VD(uitime2_adc1_value_sum);   // 输出ADC1的电压值VD1=Vref*uitime2_adc1_value_sum/16/1024
  332.            uint_to_ascii(uiadc1_value,s1);
  333.            putstring("D1=");             // uart输出ADC1
  334.            putstring(s1);
  335.            putstring("mV ");
  336.            lcd_write_string(14,0,s1);       // LCD显示
  337.           
  338.            //uart输出ADC2的电压值
  339.          uiadc2_value=cal_VD(uitime2_adc2_value_sum);   // 输出ADC2的电压值VD2=Vref*uitime2_adc2_value_sum/16/1024
  340.            uint_to_ascii(uiadc2_value,s1);
  341.            putstring("D2=");             // uart输出ADC2
  342.            putstring(s1);
  343.            putstring("mV ");
  344.            lcd_write_string(3,1,s1);       // LCD显示
  345.         
  346.            //uart输出ADC3的电压值
  347.          uiadc3_value=cal_VD(uitime2_adc3_value_sum);   // 输出ADC3的电压值VD3=Vref*uitime2_adc3_value_sum/16/1024
  348.            uint_to_ascii(uiadc3_value,s1);
  349.              putstring("D3=");             //  uart输出ADC3
  350.            putstring(s1);
  351.            putstring("mV ");
  352.            lcd_write_string(14,1,s1);       // LCD显示

  353.            uint_to_ascii(OCR1A,s1);         // uart输出TIME1 比较寄存器A 的值
  354.            putstring(" 1A=");             // uart输出
  355.            putstring(s1);

  356.            uint_to_ascii(OCR1B,s1);         // uart输出TIME1 比较寄存器B 的值
  357.            putstring(" 1B=");             // uart输出
  358.            putstring(s1);

  359.            ulong_to_ascii(time2_count/10,s1);  // uart输出TIME2秒计数值
  360.            putstring(" tn=");         // uart输出
  361.            putstring(s1);
  362.            putchar('s');
  363.           
  364.            putchar_ENTER();               // uart输出回车换行
  365.   }  // *********ADC显示  end*********

  366. /**************  数控电源相关子程序   *********************/  
  367. void DCpower(void)                     //  数控电源功能模块
  368.   {  
  369.      //3*4键盘扫描
  370.      /*扫描1*/
  371.      DDRD  &=~((1<<PD3)|(1<<PD4)|(1<<PD5));  // SET1、2、3(PD3、4、5)(S12,S11,S10)三键输入
  372.      PORTD |= ((1<<PD3)|(1<<PD4)|(1<<PD5));  // 置上拉电阻
  373.      PORTD& =~(1<<PD2);               // 使SET0(PD2)脚输出0,扫描SET1、2、3(PD3、4、5)脚
  374.      DDRD  |= (1<<PD2);
  375.      while((PIND& 0x38) != 0x38)
  376.          {
  377.            delay_ms(1);
  378.            if((PIND& 0x38) == 0x30)                       // SET1(PD3=0) S12键按下  PWMA电压快速递增
  379.                {
  380.                    if(uiVout_set<2451)                 // 限定电压不超过25.00V
  381.                    {
  382.                        uiVout_set +=50;
  383.                        OCR1A = PWM_Vout_to_count(uiVout_set);  // 电压值转换成PWMA值
  384.                    }
  385.                  }  
  386.            if((PIND& 0x38) == 0x28)                       //SET2(PD4=0) S11键按下  PWMA电压快速递减
  387.                {
  388.                    if(uiVout_set>49)  
  389.                    {
  390.                        uiVout_set -=50;
  391.                        OCR1A = PWM_Vout_to_count(uiVout_set);  // 电压值转换成PWMA值
  392.                    }
  393.                  }
  394.            if((PIND& 0x38) == 0x18)                   //SET3(PD5=0) S10键按下  ATX电源打开
  395.                {
  396.              power_ON();
  397.                  }  
  398.            delay_ms(1);
  399.            DCpower_display();
  400.            for(num1=0;num1<30;num1++)
  401.              {
  402.                if((PIND& 0x38) == 0x38)  return;
  403.                delay_ms(10);
  404.              }
  405.          }
  406.     
  407.      /*扫描2*/
  408.      DDRD  &=~((1<<PD2)|(1<<PD4)|(1<<PD5));  // SET0、2、3(PD2、4、5)(S22,S21,S20)三键输入
  409.      PORTD |= ((1<<PD2)|(1<<PD4)|(1<<PD5));  // 置上拉电阻
  410.      PORTD& =~(1<<PD3);               // 使SET1(PD3)脚输出0,扫描SET0、2、3(PD2、4、5)脚
  411.      DDRD  |= (1<<PD3);
  412.      while((PIND& 0x34) != 0x34)
  413.          {
  414.            delay_ms(1);
  415.            if((PIND& 0x34) == 0x30)                       // SET0(PD2=0) S22键按下  PWMA电压慢速递增
  416.                {
  417.                    if(uiVout_set<2500)                 // 限定电压不超过25.00V
  418.                    {
  419.                        uiVout_set +=1;
  420.                        OCR1A = PWM_Vout_to_count(uiVout_set);   // 电压值转换成PWMA值
  421.                    }
  422.                  }  
  423.            if((PIND& 0x34) == 0x24)                       //SET2(PD4=0) S21键按下  PWMA电压慢速递减
  424.                {
  425.                    if(uiVout_set>0)  
  426.                    {
  427.                        uiVout_set -=1;
  428.                        OCR1A = PWM_Vout_to_count(uiVout_set);  // 电压值转换成PWM值
  429.                    }
  430.                  }
  431.            if((PIND& 0x34) == 0x14)                   //SET3(PD5=0) S20键按下  ATX电源关闭
  432.                {
  433.                    power_OFF();
  434.                  }  
  435.            delay_ms(1);
  436.            DCpower_display();
  437.            for(num1=0;num1<30;num1++)
  438.              {
  439.                if((PIND& 0x34) == 0x34)  return;
  440.                delay_ms(10);
  441.              }
  442.          }
  443.         
  444.      /*扫描3*/
  445.      DDRD  &=~((1<<PD2)|(1<<PD3)|(1<<PD5));  // SET0、1、3(PD2、3、5)(S32,S31,S30)三键输入
  446.      PORTD |= ((1<<PD2)|(1<<PD3)|(1<<PD5));  // 置上拉电阻
  447.      PORTD& =~(1<<PD4);               // 使SET2(PD4)脚输出0,扫描SET0、1、3(PD2、3、5)脚
  448.      DDRD  |= (1<<PD4);
  449.      while((PIND& 0x2c) != 0x2c)
  450.          {
  451.            delay_ms(1);
  452.            if((PIND& 0x2c) == 0x28)                       //SET0(PD2=0) S32键按下  PWMB电压快速递增
  453.                {
  454.                    if(uiIout_set<3901)                 // 限定电流不超过4.000A
  455.                    {
  456.                        uiIout_set +=100;
  457.                        OCR1B = PWM_Iout_to_count(uiIout_set);  // 电流值转换成PWMB值
  458.                    }
  459.                  }  
  460.            if((PIND& 0x2c) == 0x24)                       //SET1(PD3=0) S31键按下  PWMB电压快速递减
  461.                {
  462.                    if(uiIout_set>99)  
  463.                    {
  464.                        uiIout_set -=100;
  465.                        OCR1B = PWM_Iout_to_count(uiIout_set);  // 电流值转换成PWMB值
  466.                    }
  467.                  }
  468.            if((PIND& 0x2c) == 0x0c)                   // SET3(PD5=0) S30键按下 "CANCEL"键 当前功能退出  
  469.                {
  470.                    config_temp++;                     // 改变config_temp值,令config_temp!=config
  471.                  }  
  472.            delay_ms(1);
  473.            DCpower_display();
  474.            for(num1=0;num1<30;num1++)
  475.              {
  476.                if((PIND& 0x2c) == 0x2c)  return;
  477.                delay_ms(10);
  478.              }
  479.          }

  480.      /*扫描4*/
  481.      DDRD  &=~((1<<PD2)|(1<<PD3)|(1<<PD4));  // SET0、1、2(PD2、3、4)(S42,S41,S40)三键输入
  482.      PORTD |= ((1<<PD2)|(1<<PD3)|(1<<PD4));  // 置上拉电阻
  483.      PORTD& =~(1<<PD5);               // 使SET3(PD5)脚输出0,扫描SET0、1、2(PD2、3、4)脚
  484.      DDRD  |= (1<<PD5);
  485.      while((PIND& 0x1c) != 0x1c)
  486.          {
  487.            delay_ms(1);
  488.            if((PIND& 0x1c) == 0x18)                       // SET0(PD2=0) S42键按下 PWMB电压慢速递增
  489.                {
  490.                    if(uiIout_set<4000)                 // 限定电流不超过4.000A
  491.                    {
  492.                        uiIout_set +=1;
  493.                        OCR1B = PWM_Iout_to_count(uiIout_set);   // 电流值转换成PWMB值
  494.                    }
  495.                  }  
  496.            if((PIND& 0x1c) == 0x14)                       // SET1(PD3=0) S41键按下 PWMB电压慢速递减
  497.                {
  498.                    if(uiIout_set>0)  
  499.                    {
  500.                        uiIout_set -=1;
  501.                        OCR1B = PWM_Iout_to_count(uiIout_set);   // 电流值转换成PWMB值
  502.                    }
  503.                  }
  504.            if((PIND& 0x1c) == 0x0c)                   // SET2(PD4=0) S40键按下  
  505.                {
  506.                   
  507.                  }  
  508.            delay_ms(1);
  509.            DCpower_display();
  510.            for(num1=0;num1<30;num1++)
  511.              {
  512.                if((PIND& 0x1c) == 0x1c)  return;
  513.                delay_ms(10);
  514.              }
  515.          }
  516.    }

  517. void power_ON(void)                 // 开关电源打开
  518.   {
  519.      ATX_CTL_DDR  |= (1<<ATX_CTL);         //
  520.      ATX_CTL_PORT |= (1<<ATX_CTL);         // 置1
  521.   }  
  522. void power_OFF(void)                 // 开关电源关闭
  523.   {
  524.    ATX_CTL_DDR  |=  (1<<ATX_CTL);       //  
  525.      ATX_CTL_PORT& =~ (1<<ATX_CTL);       // 置0
  526.   }
  527. /**************  数控电源相关子程序   *************** END */  

  528.   
  529. void program_set(void)               // 功能模块选择设定
  530.   {
  531.    //循环3*4键盘扫描
  532.    while(1)
  533.      {
  534.      /*扫描1*/
  535.      DDRD  &=~((1<<PD3)|(1<<PD4)|(1<<PD5));  // SET1、2、3(PD3、4、5)(S12,S11,S10)三键输入
  536.      PORTD |= ((1<<PD3)|(1<<PD4)|(1<<PD5));  // 置上拉电阻
  537.      PORTD& =~(1<<PD2);               // 使SET0(PD2)脚输出0,扫描SET1、2、3(PD3、4、5)脚
  538.      DDRD  |= (1<<PD2);
  539.      while((PIND& 0x38) != 0x38)
  540.          {
  541.            delay_ms(1);
  542.            if((PIND& 0x38) == 0x30)                       //SET1(PD3=0) S12 "1"键按下  选择数控电源
  543.                {
  544.                        config_temp = 0x10;
  545.                  }  
  546.            if((PIND& 0x38) == 0x28)                       //SET2(PD4=0) S11 "5"键按下  
  547.                {
  548.                  }
  549.            if((PIND& 0x38) == 0x18)                   //SET3(PD5=0) S10键按下  
  550.                {
  551.                  }  
  552.            delay_ms(50);
  553.          }
  554.     
  555.      /*扫描2*/
  556.      DDRD  &=~((1<<PD2)|(1<<PD4)|(1<<PD5));  // SET0、2、3(PD2、4、5)(S22,S21,S20)三键输入
  557.      PORTD |= ((1<<PD2)|(1<<PD4)|(1<<PD5));  // 置上拉电阻
  558.      PORTD& =~(1<<PD3);               // 使SET1(PD3)脚输出0,扫描SET0、2、3(PD2、4、5)脚
  559.      DDRD  |= (1<<PD3);
  560.      while((PIND& 0x34) != 0x34)
  561.          {
  562.            delay_ms(1);
  563.            if((PIND& 0x34) == 0x30)                       //SET0(PD2=0) S22键按下  
  564.                {
  565.                  }  
  566.            if((PIND& 0x34) == 0x24)                       //SET2(PD4=0) S21键按下  
  567.                {
  568.                  }
  569.            if((PIND& 0x34) == 0x14)                   //SET3(PD5=0) S20键按下  
  570.                {
  571.                  }  
  572.            delay_ms(50);
  573.          }
  574.         
  575.      /*扫描3*/
  576.      DDRD  &=~((1<<PD2)|(1<<PD3)|(1<<PD5));  // SET0、1、3(PD2、3、5)(S32,S31,S30)三键输入
  577.      PORTD |= ((1<<PD2)|(1<<PD3)|(1<<PD5));  // 置上拉电阻
  578.      PORTD& =~(1<<PD4);               // 使SET2(PD4)脚输出0,扫描SET0、1、3(PD2、3、5)脚
  579.      DDRD  |= (1<<PD4);
  580.      while((PIND& 0x2c) != 0x2c)
  581.          {
  582.            delay_ms(1);
  583.            if((PIND& 0x2c) == 0x28)                       //SET0(PD2=0) S32键按下  
  584.                {
  585.                  }  
  586.            if((PIND& 0x2c) == 0x24)                       //SET1(PD3=0) S31键按下  
  587.                {
  588.                  }
  589.            if((PIND& 0x2c) == 0x0c)                   // SET3(PD5=0) S30键按下 "CANCEL"键 当前功能退出  
  590.                {
  591. ……………………

  592. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
见2楼

评分

黑币 +50
收起理由
+ 50
共享资料的黑币奖励!

查看全部评分

沙发
ID:696930发表于 2020-10-9 10:19|只看该作者
ATMEGA8数控电源和电压自动校正的C程序

ATMEGA8数控电源和电压自动校正的C程序.zip

114.33 KB, 下载次数: 54, 下载积分: 黑币 -5

板凳
ID:81138发表于 2021-1-29 09:05|只看该作者
非此专业请图文可以吗
地板
ID:405183发表于 2022-12-27 11:17来自手机|只看该作者
有没有中文说明呀

手机版|小黑屋|51黑电子论坛|51黑电子论坛6群QQ管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网