找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4197|回复: 3
收起左侧

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

[复制链接]
ID:696930 发表于 2020-10-9 10:16 | 显示全部楼层 |阅读模式
先用ISP下载线把boot.hex写入M8.
FUSE设定为外部晶振(4.096MHz),启动硬件"看门狗",和BOOT区启动

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

电路原理图如下:
M8控制部分2.jpg

单片机源程序如下:
  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楼

评分

参与人数 1黑币 +50 收起 理由
admin + 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 单片机教程网

快速回复 返回顶部 返回列表