找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于请问,51单片机的数控可调稳压电源的程序没有错误但是仿真失败,是哪里有问题吗?

[复制链接]
跳转到指定楼层
楼主
目的:用51单片机控制按键来增加减少占空比,达到改变占空比来改变输出电压并进行ADC转换后通过LCD1602显示出此时输出电压。
问题:1.程序编译时没有错误,但是用proteus烧录仿真后没有任何反应
                  

         2.程序里面的问题:
         
程序如下,希望能有大佬帮忙找出程序的问题。谢谢各位了!!!!!!!!
  1. #include<reg51.h>
  2. #include<intrins.h>        //包含_nop_()函数定义的头文件
  3. #define uint unsigned int
  4. #define uchar unsigned char


  5. uchar time;

  6. double count=20; //定义占空比,并初始占空比为26%

  7. sbit PWM=P1^7; //P2^0口输出PWM

  8. sbit key_add=P3^4; //占空比增加的按键 的I/O口

  9. sbit key_dec=P3^5; //占空比减少的按键 的I/O口

  10. /************ADC0832端口引脚定义***************/

  11. sbit CS=P1^2;  //将CS位定义为 P1.2引脚
  12. sbit CLK=P1^0;
  13. sbit DIO=P1^1;

  14. /***********液晶端口定义**********/

  15. sbit RS=P1^5;        //寄存器选择位
  16. sbit RW=P1^4;        //读写选择位
  17. sbit E=P1^3;        //使能信号位
  18. sbit BF=P0^7; //忙碌标志位

  19. /**************全局变量声明***********/

  20. unsigned char code digit[10]={"0123456789"};//定义字符数组显示数字
  21. unsigned char code Str[]={"Volt="}; // 说明显示的是电压

  22. /************函数声明**************/

  23. void delayxms(uint z); //延时

  24. void PWM_add(); //增加占空比

  25. void PWM_dec(); //减少占空比

  26. void timer0_init(); //定时器0初始化

  27. bit BusyTest(void); //判断液晶模块忙碌状态
  28. void WriteInstructuon (unsigned char dictate);//将模式设置命令或显示地址写入液晶模块
  29. void WriteAddress ( unsigned char x); //指定字符显示的实际地址
  30. void WriteData( unsigned char y); //将数据(标准ASCII码)写入液晶模块
  31. void LcdInitiate(void);        //        LCD显示模式初始化设置
  32. void display_volt(void);        //显示电压符号
  33. void display_dot(void);        //显示电压小数点
  34. void display_V(void);        //显示电压的单位
  35. void display1(unsigned char x);        //显示电压的整数部分
  36. void display2(unsigned char x);        //显示电压的小数部分
  37. unsigned char A_D();        //模数转换
  38. unsigned int AD_val;                //储存模数转换后的值
  39. unsigned char Int,Dec;                //分别储存转换后的整数与小数部分

  40. /*********主函数********************/

  41. void main()

  42. {

  43. timer0_init();

  44. delayxms(5);

  45. while(1)

  46. {
  47. unsigned int AD_val;                //储存模数转换后的值
  48. unsigned char Int,Dec;                //分别储存转换后的整数与小数部分
  49.        
  50. PWM_add();

  51. PWM_dec();


  52.        
  53. LcdInitiate();                //液晶初始化
  54. delayxms(5);                //延时,给硬件反应时间
  55. display_volt();                //显示电压符号
  56. display_dot();                //显示电压的小数点
  57. display_V();                //显示电压单位

  58. while(1)
  59. {
  60.         AD_val=A_D();                //进行数模转换
  61.         Int=(AD_val)/51;                //计算整数部分
  62.         Dec=(AD_val%51)*100/51;                //小数部分计算
  63.                 display1(Int);        //显示整数
  64.         display2(Dec);                //显示小数
  65.         delayxms(250);
  66.                 break;
  67. }
  68.   break;
  69. }

  70. }


  71. /****************延时处理**********************/

  72. void delayxms(uint z) //延时xms程序

  73. {

  74. uint x,y;

  75. for(y=z;x>0;x--)

  76. for(y=110;y>0;y--);

  77. }



  78. void PWM_add() //电机加速

  79. {

  80. if(key_add==0)

  81. {

  82. delayxms(2); //此处时间不能太长,否者会的中断产生冲突

  83. if(key_add==0)

  84. {

  85. count+=1; //每按一次加速按键占空比加1

  86. if(count>=100) //限定占空比上限

  87. {

  88. count=100;

  89. }

  90. }

  91. while(!key_add);

  92. }

  93. }


  94. void PWM_dec()//电机减速

  95. {

  96. if(key_dec==0)

  97. {

  98. delayxms(2);//此处时间不能太长,否者会的中断产生冲突

  99. if(key_dec==0)

  100. {

  101. count-=1; //每按一次减速按键占空比减0.5

  102. if(count<=0) //限定占空比下限

  103. {

  104. count=0;

  105. }

  106. }

  107. while(!key_dec);

  108. }

  109. }


  110. /***********定时器0初始化***********/

  111. void timer0_init()

  112. {

  113. TMOD=0x01; //定时器0工作于方式1

  114. TH0=(65536-10)/256;

  115. TL0=(65536-10)%256;

  116. TR0=1;

  117. ET0=1;

  118. EA=1;

  119. }


  120. /**************定时0中断处理******************/

  121. void timer0_int() interrupt 1

  122. {


  123. TR0=0; //设置定时器初值期间,关闭定时器

  124. TH0=(65536-10)/256;

  125. TL0=(65536-10)%256;

  126. TR0=1;


  127. time++;

  128. if(time<count) //count为占空比

  129. {

  130. PWM=1; //输出高电平

  131. }

  132. else

  133. PWM=0;

  134. if(time>=100)

  135. {

  136. time=0;

  137. }

  138. }

  139. /*******************判断液晶忙碌状态******************/
  140. /********* result=1,忙碌;=0,不忙 *************/

  141. bit BusyTest(void)
  142. {
  143. bit result;
  144.         RS=0;                        //RS为低电平,RW为高时,可以读状态
  145.         RW=1;
  146.         E=1;                        //=1时才允许读写
  147.         _nop_();                //空操作四个机器周期,给硬件反应
  148.         _nop_();
  149.         _nop_();
  150.         _nop_();
  151.         result=BF;                        //忙碌标志赋给result,将E恢复低电平
  152.         E=0;
  153.         return result;
  154. }

  155. /*************将模式设置指令或显示地址写入液晶***************/

  156. void WriteInstruction (unsigned char dictate)
  157. {
  158.   while(BusyTest()==1);                //忙时等待
  159.         RS=0;
  160.         RW=0;
  161.         E=0;
  162.   _nop_();                //空操作两个机器周期,给硬件反应
  163.         _nop_();
  164.         P0=dictate;                        //数据送入P0,即写入指令或地址
  165.         _nop_();                //空操作四个机器周期,给硬件反应
  166.         _nop_();
  167.         _nop_();
  168.         _nop_();
  169.         E=1;                                //E置高电平
  170.         _nop_();                //空操作四个机器周期,给硬件反应
  171.         _nop_();
  172.         _nop_();
  173.         _nop_();
  174.         E=0;                                //E由高电平跳到低电平,液晶开始执行命令
  175.        
  176. }

  177. /**************指定字符显示的实际地址************/

  178. void WriteAddress(unsigned char x)
  179. {
  180.                 WriteInstruction(x|0x80);                        //显示位置的方法规定为80H+地址码x
  181. }

  182. /***************将数据写入液晶模块************/

  183. void WriteData(unsigned char y)
  184. {
  185.                 while(BusyTest()==1);
  186.                 RS=1;                        //RS为高电平,RW为低电平时,可以写入数据
  187.                 RW=0;
  188.                 E=0;                        //E置低电平(根据表8-6,写指令时,E为高脉冲, 就是让E从0到1发生正跳变,所以应先置"0".
  189.   
  190.                 P0=y;                        //数据送入P0,即将数据写入液晶
  191.                 _nop_();                //空操作四个机器周期,给硬件反应
  192.                 _nop_();
  193.                 _nop_();
  194.                 _nop_();
  195.                 E=1;                                //E置高电平
  196.                 _nop_();                //空操作四个机器周期,给硬件反应
  197.                 _nop_();
  198.                 _nop_();
  199.                 _nop_();
  200.                 E=0;                                //E由高电平跳到低电平,液晶开始执行命令
  201.        
  202. }

  203. /************LCD显示模式初始化*************/

  204. void LcdInitiate(void)
  205. {
  206.        
  207.                  delayxms(15);                        //首次给一个较长反应时间
  208.          WriteInstruction(0x38);                //显模式设置,16x2显示,5x7点阵,8位数据接口
  209.                  delayxms(5);
  210.          WriteInstruction(0x38);
  211.                  delayxms(5);
  212.          WriteInstruction(0x38);                        //连续三次,确保初始化成功
  213.                  delayxms(5);
  214.          WriteInstruction(0x0c);                        //显示模式:显示开,无光标,不闪烁
  215.                  delayxms(5);
  216.          WriteInstruction(0x06);                        //显示模式:光标右移,字符不移
  217.                  delayxms(5);
  218.          WriteInstruction(0x01);                        //清屏,将显示内容清除
  219.                 delayxms(5);
  220.          
  221. }

  222. /*********************显示电压符号*******************/

  223. void display_volt(void)
  224. {
  225.                 unsigned char i;
  226.          WriteAddress(0x03);                //写显示地址,将在第2行第一列开始显示
  227.          i=0;                                //从第一个字符开始显示
  228.          while(Str[i]!='\0')                                        //只要没有写到结束标志就继续写
  229.          {
  230.                         WriteData(Str[i]);                                        //将字符常量写入LCD
  231.                         i++;                                                                //指向下一个字符
  232.          }
  233. }

  234. /********************显示电压的小数点*****************/
  235. void display_dot(void)
  236. {
  237.                 WriteAddress(0x09);                                        //写显示地址,将在第一行第10列开始显示
  238.                 WriteData('.');                                                        //将小数点的字符常量写入LCD
  239. }

  240. /*******************显示电压的单位*******************/

  241. void display_V(void)
  242. {
  243.                 WriteAddress(0x0c);                                //写显示地址,将在第2行第13列开始显示
  244.                 WriteData('V');                                                        //将字符常量写入LCD
  245. }

  246. /**********************显示电压的整数部分***********************/

  247. void display1(unsigned char x)
  248. {
  249.                 WriteAddress(0x08);                                        //写显示地址,将在第2行第7列开始显示
  250.                 WriteData(digit[x]);                                                        //将百位数字的字符常量写入LCD
  251. }

  252. /*******************显示电压的小数部分****************/

  253. void display2(unsigned char x)
  254. {
  255.                 unsigned char i,j;
  256.                 j=x/10;                                                //取小数点后第一位
  257.          j=x%10;                                                //取小数点后第二位
  258.          WriteAddress(0x0a);                                        //写显示地址,将在第1行第11列开始显示
  259.                 WriteData(digit[i]);                                                        //将小数后的第一位数字字符常量写入LCD
  260.          WriteData(digit[j]);                                                        //将小数后的第二位数字字符常量写入LCD
  261.          
  262. }

  263. /******************模数转换********************/

  264. unsigned char A_D()
  265. {
  266.                 unsigned char i,dat;
  267.          CS=1;                                                //一个转换周期开始
  268.          CLK=0;                                        //为第一个脉冲做准备
  269.          CS=0;                                                //CS置0,片选有效
  270.          DIO=1;                                                //规定的起始信号
  271.          CLK=1;                                                //第一个脉冲
  272.          CLK=0;                                                //第一个脉冲的下降沿,此时DIO必须是高电平
  273.          DIO=1;                                                //通道选择信号
  274.          CLK=1;                                                //第二个脉冲,第2、3个脉冲下沉之前,DI必须跟别输入两位数据用于选择通道,这里选通道CH0
  275.          CLK=0;                                                //第二个脉冲下降沿
  276.          
  277.          DIO=0;                                                //选择通道0
  278.          CLK=1;                                                        //第三个脉冲
  279.          CLK=0;
  280.          DIO=1;                                                        //第三个脉冲下沉后DIO失去作用,置一
  281.          CLK=1;                                                        //第四个脉冲
  282.          
  283.          for(i=0;i<8;i++)
  284.          {
  285.                         CLK=1;                                        //第四个脉冲
  286.                         CLK=0;
  287.                         dat<<=1;                                //将下面储存的低位数据右移
  288.                  dat|=(unsigned char)DIO;                                //将输出数据DIO通过或运算储存在dat最低位
  289.          }
  290.          CS=1;                //片选无效
  291.          return        dat;                                        //将读出的数据返回
  292. }
复制代码

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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