找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5468|回复: 4
打印 上一主题 下一主题
收起左侧

ATMEGA8数控电源制作资料 源码 PCB 仿真

  [复制链接]
跳转到指定楼层
楼主

所有资料下载(源码 PCB 仿真):
ATMEGA8数控电源制作资料.rar (202.04 KB, 下载次数: 154)


下面是数控电压的仿真原理图:




源程序:
  1. /*********************************************
  2. * vim: set sw=8 ts=8 si :
  3. * Author: Guido Socher, Copyright: GPL
  4. * This is the main program for the digital dc power supply
  5. * Chip type           : ATMEGA8
  6. * Clock frequency     : Internal clock 4 Mhz
  7. *********************************************/
  8. #include <avr/io.h>
  9. #include <inttypes.h>
  10. #include <avr/interrupt.h>
  11. #define F_CPU 4000000UL  // 4 MHz
  12. #include <util/delay.h>
  13. #include "lcd.h"
  14. #include "dac.h"
  15. #include "kbd.h"
  16. #include "analog.h"
  17. #include "avr_compat.h"
  18. #include "hardware_settings.h"
  19. #include "i2c_avr.h"
  20. #include <stdlib.h> // atoi
  21. #include <string.h>
  22. #include <avr/eeprom.h>

  23. #define SWVERSION "ver: ddcp-0.5.0"

  24. static int set_val[2];
  25. static int measured_val[2];
  26. static char i2c_buf[MAX_BUF_LEN+1];
  27. // the set values but converted to ADC steps
  28. static int set_val_adcUnits[2];
  29. static unsigned char bpress=0;

  30. void delay_ms(unsigned int ms)
  31. /* delay for a minimum of <ms> */
  32. {
  33.         // we use a calibrated macro. This is more
  34.         // accurate and not so much compiler dependent
  35.         // as self made code.
  36.         while(ms){
  37.                 _delay_ms(0.96);
  38.                 ms--;
  39.         }
  40. }

  41. // Convert a integer which is representing a float into a string.
  42. // decimalpoint_pos sets the decimal point after 2 pos: e.g 74 becomes "0.74"
  43. // The integer may not be larger than 10000.
  44. // The integer must be a positive number.
  45. // spacepadd can be used to add a leading speace if number is less than 10
  46. static void int_to_ascii(int inum,char *outbuf,signed char decimalpoint_pos,signed char spacepadd){
  47.         signed char i,j;
  48.         char chbuf[8];
  49.         j=0;
  50.         while(inum>9 && j<7){
  51.                 // zero is ascii 48:
  52.                 chbuf[j]=(char)48+ inum-((inum/10)*10);
  53.                 inum=inum/10;
  54.                 j++;
  55.                 if(decimalpoint_pos==j){
  56.                         chbuf[j]='.';
  57.                         j++;
  58.                 }
  59.         }
  60.         chbuf[j]=(char)48+inum; // most significant digit
  61.         decimalpoint_pos--;
  62.         while(j<decimalpoint_pos){
  63.                 j++;
  64.                 chbuf[j]='0';
  65.         }
  66.         if (spacepadd && j > (decimalpoint_pos+2)){
  67.                 // no leading space padding needed
  68.                 spacepadd=0;
  69.         }
  70.         if(decimalpoint_pos==j){
  71.                 j++;
  72.                 chbuf[j]='.';
  73.                 j++;
  74.                 chbuf[j]='0'; // leading zero
  75.         }
  76.         if (spacepadd){
  77.                 j++;
  78.                 chbuf[j]=' '; // leading space padding: "9.50" becomes " 9.50"
  79.         }
  80.         // now reverse the order
  81.         i=0;
  82.         while(j>=0){
  83.                 outbuf[i]=chbuf[j];
  84.                 j--;
  85.                 i++;
  86.         }
  87.         outbuf[i]='\0';
  88. }

  89. // convert voltage values to adc values, disp=10 is 1.0V
  90. static int disp_u_to_adc(int disp){
  91.         return((int)(disp * 102.3) / (ADC_REF * U_DIVIDER));
  92. }
  93. // calculate the needed adc offset for voltage drop on the
  94. // current measurement shunt (the shunt has about 0.5 Ohm =1/2 Ohm)
  95. static int disp_i_to_u_adc_offset(int disp){
  96.         return(disp_u_to_adc(disp/20));
  97. }
  98. // convert adc values to voltage values, disp=10 is 1.0V
  99. // disp_i_val is needed to calculate the offset for the voltage drop over
  100. // the current measurement shunt
  101. static int adc_u_to_disp(int adcunits,int disp_i_val){
  102.         int adcdrop;
  103.         adcdrop=disp_i_to_u_adc_offset(disp_i_val);
  104.         if (adcunits < adcdrop){
  105.                 return(0);
  106.         }
  107.         adcunits=adcunits-adcdrop;
  108.         return((int)(((adcunits /102.3)* ADC_REF * U_DIVIDER)+0.6));
  109. }
  110. // convert adc values to current values, disp=10 needed to be printed
  111. // by the printing function as 0.10 A
  112. static int disp_i_to_adc(int disp){
  113.         return((int) (((disp * 10.23)* I_RESISTOR) / ADC_REF));
  114. }
  115. // convert adc values to current values, disp=10 needed to be printed
  116. // by the printing function as 0.10 A
  117. static int adc_i_to_disp(int adcunits){
  118.         return((int) (((adcunits* ADC_REF)/(10.23 * I_RESISTOR))+0.6));
  119. }

  120. static void store_permanent(void){
  121.         int tmp;
  122.         signed char changeflag=1;
  123.         lcd_clrscr();
  124.         if (eeprom_read_byte((uint8_t *)0x0) == 19){
  125.                 changeflag=0;
  126.                 // ok magic number matches accept values
  127.                 tmp=eeprom_read_word((uint16_t *)0x04);
  128.                 if (tmp != set_val[1]){
  129.                         changeflag=1;
  130.                 }
  131.                 tmp=eeprom_read_word((uint16_t *)0x02);
  132.                 if (tmp != set_val[0]){
  133.                         changeflag=1;
  134.                 }
  135.         }
  136.         if (changeflag){
  137.                 lcd_puts_P("setting stored");
  138.                 eeprom_write_byte((uint8_t *)0x0,19); // magic number
  139.                 eeprom_write_word((uint16_t *)0x02,set_val[0]);
  140.                 eeprom_write_word((uint16_t *)0x04,set_val[1]);
  141.         }else{
  142.                 if (bpress> 5){
  143.                         // display software version after long press
  144.                         lcd_puts_P(SWVERSION);
  145.                         lcd_gotoxy(0,1);
  146.                         lcd_puts_P("tuxgraphics.org");
  147.                 }else{
  148.                         lcd_puts_P("already stored");
  149.                 }
  150.         }
  151.         delay_ms(200);
  152. }

  153. // check the keyboard
  154. static unsigned char check_buttons(void){
  155.         if (check_u_button(&(set_val[1]))){
  156.                 if(set_val[1]>U_MAX){
  157.                         set_val[1]=U_MAX;
  158.                 }
  159.                 return(1);
  160.         }
  161.         if (check_i_button(&(set_val[0]))){
  162.                 if(set_val[0]>I_MAX){
  163.                         set_val[0]=I_MAX;
  164.                 }
  165.                 return(1);
  166.         }
  167.         if (check_store_button()){
  168.                 store_permanent();
  169.                 return(2);
  170.         };
  171.         return(0);
  172. }

  173. void check_i2c_interface(void){
  174.         if (i2c_get_received_data(i2c_buf)){
  175.                 if (i2c_buf[0]=='i'){
  176.                         if (i2c_buf[1]=='=' && i2c_buf[2]!='\0'){
  177.                                 set_val[0]=atoi(&i2c_buf[2]);
  178.                                 if(set_val[0]>I_MAX){
  179.                                         set_val[0]=I_MAX;
  180.                                 }
  181.                                 if(set_val[0]<0){
  182.                                         set_val[0]=0;
  183.                                 }
  184.                                 i2c_send_data("ok");
  185.                         }else{
  186.                                 int_to_ascii(measured_val[0],i2c_buf,2,0);
  187.                                 strcat(i2c_buf,"A");
  188.                                 i2c_send_data(i2c_buf);
  189.                         }
  190.                 }else if (i2c_buf[0]=='s'){
  191.                         store_permanent();
  192.                         i2c_send_data("ok");
  193.                 }else if (i2c_buf[0]=='u'){
  194.                         if (i2c_buf[1]=='=' && i2c_buf[2]!='\0'){
  195.                                 set_val[1]=atoi(&i2c_buf[2]);
  196.                                 if(set_val[1]>U_MAX){
  197.                                         set_val[1]=U_MAX;
  198.                                 }
  199.                                 if(set_val[1]<0){
  200.                                         set_val[1]=0;
  201.                                 }
  202.                                 i2c_send_data("ok");
  203.                         }else{
  204.                                 int_to_ascii(measured_val[1],i2c_buf,1,0);
  205.                                 strcat(i2c_buf,"V");
  206.                                 i2c_send_data(i2c_buf);
  207.                         }
  208.                 }else{
  209.                         i2c_send_data("err");
  210.                 }
  211.         }
  212. }

  213. int main(void)
  214. {
  215.         char out_buf[20+1];
  216.         measured_val[0]=0;
  217.         measured_val[1]=0;
  218.         init_dac();
  219.         lcd_init(LCD_DISP_ON);
  220.         init_kbd();
  221.         set_val[0]=15;set_val[1]=50; // 150mA and 5V
  222.         if (eeprom_read_byte((uint8_t *)0x0) == 19){
  223.                 // ok magic number matches accept values
  224.                 set_val[1]=eeprom_read_word((uint16_t *)0x04);
  225.                 set_val[0]=eeprom_read_word((uint16_t *)0x02);
  226.         }
  227.         // I2C also called TWI, slave address=3
  228.         i2c_init(3,1,0);
  229.         sei();
  230.         i2c_send_data("on");
  231.         init_analog();
  232.         while (1) {

  233.                 // current
  234.                 measured_val[0]=adc_i_to_disp(getanalogresult(0));
  235.                 set_val_adcUnits[0]=disp_i_to_adc(set_val[0]);
  236.                 set_target_adc_val(0,set_val_adcUnits[0]);
  237.                 // voltage
  238.                 measured_val[1]=adc_u_to_disp(getanalogresult(1),measured_val[0]);
  239.                 set_val_adcUnits[1]=disp_u_to_adc(set_val[1])+disp_i_to_u_adc_offset(measured_val[0]);
  240.                 set_target_adc_val(1,set_val_adcUnits[1]);

  241.                 // voltage
  242.                 lcd_clrscr();
  243.                 int_to_ascii(measured_val[1],out_buf,1,1);
  244.                 lcd_puts(out_buf);
  245.                 lcd_puts("V ");
  246.                 int_to_ascii(set_val[1],out_buf,1,1);
  247.                 lcd_putc('[');
  248.                 lcd_puts(out_buf);
  249.                 lcd_putc(']');
  250.                 if (!is_current_limit()){
  251.                         // put a marker to show which value is currenlty limiting
  252.                         lcd_puts("<-");
  253.                 }

  254.                 check_i2c_interface();

  255.                 // current
  256.                 lcd_gotoxy(0,1);
  257.                 int_to_ascii(measured_val[0],out_buf,2,0);
  258.                 lcd_puts(out_buf);
  259.                 lcd_puts("A ");
  260.                 int_to_ascii(set_val[0],out_buf,2,0);
  261.                 lcd_putc('[');
  262.                 lcd_puts(out_buf);
  263.                 lcd_putc(']');
  264.                 if (is_current_limit()){
  265.                         // put a marker to show which value is currenlty limiting
  266.                         lcd_puts("<-");
  267.                 }
  268.                 //dbg
  269.                 //int_to_ascii(is_dacval(),out_buf,0,0);
  270.                 //lcd_puts(out_buf);
  271.                 check_i2c_interface();

  272.                 // the buttons must be responsive but they must not
  273.                 // scroll too fast if pressed permanently
  274.                 if (check_buttons()==0){
  275.                         // no buttons pressed
  276.                         delay_ms(100);
  277.                         bpress=0;
  278.                         check_i2c_interface();
  279.                         check_buttons();
  280.                         delay_ms(150);
  281.                 }else{
  282.                         // button press
  283.                         if (bpress > 11){
  284.                                 // somebody pressed permanetly the button=>scroll fast
  285.                                 delay_ms(10);
  286.                                 check_i2c_interface();
  287.                                 delay_ms(40);
  288.                         }else{
  289.                                 bpress++;
  290.                                 delay_ms(100);
  291.                                 check_i2c_interface();
  292.                                 delay_ms(150);
  293.                         }
  294.                 }
  295.         }
  296.         return(0);
  297. }

复制代码

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏8 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:228528 发表于 2017-11-20 09:32 | 只看该作者
不错的资料。。。。
回复

使用道具 举报

板凳
ID:552794 发表于 2019-6-9 10:51 | 只看该作者
详尽的资料,认真学习.
回复

使用道具 举报

地板
ID:145887 发表于 2021-11-14 15:53 | 只看该作者
资料详尽,学习学习,
回复

使用道具 举报

5#
ID:1019351 发表于 2022-4-18 16:17 | 只看该作者
资料好,让人有马上制作的冲动!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

Powered by 单片机教程网

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