找回密码
 立即注册

QQ登录

只需一步,快速开始

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

关于STC12C5A60S2单片机AD读取值跳动的问题

[复制链接]
跳转到指定楼层
楼主
之前我的程序能够读取AD值,但是会跳动,而且初始的电压不是0V,现在我程序修改以后,它是稳定了,读不了AD了是怎么回事?只能读到0.01V?


  1. #include "reg52.h"                                                   
  2. #include "intrins.h"  

  3. typedef  unsigned char uchar;                                               
  4. typedef  unsigned int uint;   
  5. #define  _Nop() _nop_()

  6. /*------------------------以下为LCD1602显示模块定义-----------------------*/
  7. unsigned char data_char_table[]= {"0123456789ABCDEF"};                        //LCD数据
  8. unsigned char Lcd_Dis1_table[] = {"Position:No.    "};                        //第一行显示框架
  9. unsigned char pos_char_table[] = {"             D  "};                        //      显示位置
  10. unsigned char Lcd_Dis2_table[] = {"Voltage :      V"};                        //第二行显示框架
  11. unsigned char num_char_table[] = {"         9A.CD V"};                        //      显示位置


  12. sbit lcd_rs_port = P2^4;                                                 //定义LCD控制端口,根据硬件调整
  13. sbit lcd_rw_port = P2^3;                                                                                
  14. sbit lcd_en_port = P2^2;
  15. #define lcd_data_port P0

  16. void lcd_delay(uchar ms);                                                                        //LCD1602 延时
  17. void lcd_busy_wait();                                                                                 //LCD1602 忙等待
  18. void lcd_command_write(uint command);                                                 //LCD1602 命令字写入
  19. void lcd_system_reset();                                                                                //LCD1602 初始化
  20. void lcd_char_write(uint x_pos,y_pos,lcd_dat);                                         //LCD1602 字符写入
  21. void lcd_bad_check();                                                                                 //LCD1602 坏点检查
  22. void Num_to_Disp(uchar i, uint Num);                                                        //显示数据处理
  23. void LcdDisp(uchar j, uint num);                                                                //液晶显示函数

  24. /*------------------------以下为ADC相应寄存器初始化及端口定义-------------*/                           
  25. /***** 定义与ADC相关的特殊功能寄存器 *****/                       
  26. sfr  ADC_CONTR =  0xBC;                 //ADC控制寄存器                    
  27. sfr  ADC_RES   =  0xBD;                 //ADC hight 8-bit result register
  28. sfr  ADC_RESL  =  0xBE;                 //ADC low 2-bit result register
  29. sfr  P1ASF     =  0x9D;                 //P1口功能控制寄存器P1ASF
  30. sfr  P1M0      =  0x92;                  //I/O模式寄存器
  31. sfr  P1M1      =  0x91;                  //I/O模式寄存器
  32. /************定义相应操作位***************/
  33. #define  ADC_POWER          0x80            //ADC电源控制位,0:关闭,1:打开
  34. #define  ADC_FLAG           0x10            //ADC结束标志位
  35. #define  ADC_START          0x08            //ADC启动控制位
  36. #define  ADC_SPEEDLL        0x00            //540 clocks___________选择转换速度

  37. /*------------------------以下为相关函数声明------------------------------*/
  38. void InitADC();                                                                                                        //ADC初始化
  39. uint GetADCResult(uchar ch);                                                                                                                                                                        
  40. void Delay(uint n);                                                                                         //延时程序
  41. void delay_1ms(uchar x);



  42. /*-------------------------------- ADC 取值 ------------------------------*/
  43. uint GetADCResult(uchar channel)
  44. {
  45.         ADC_CONTR=0x88|channel;    //开启AD转换1000 1000 即POWER SPEED1 SPEED0 ADC_FLAG   ADC_START CHS2 CHS1 CHS0
  46.         _nop_(); _nop_(); _nop_(); _nop_();//要经过4个CPU时钟的延时,其值才能够保证被设置进ADC_CONTR 寄存器         
  47. //        ADC_RES=0xdf;
  48. //        ADC_RESL=0xef;
  49.         while(!(ADC_CONTR&0x10));    //等待转换完成
  50.         ADC_CONTR&=0xe7;      //关闭AD转换,ADC_FLAG位由软件清0
  51.         return(ADC_RES*4+ADC_RESL);   //返回AD转换完成的10位数据(16进制)
  52. }



  53. /*---------------------------- 初始化ADC特殊功能寄存器 -------------------*/

  54. void InitADC( )
  55. {
  56.         
  57.           P1ASF = P1 | 0x3f;                //Set  P1.0 - P1.5 as analog input port
  58.           ADC_RES  = 0;                  //Clear previous result
  59.           ADC_RESL = 0;
  60.           ADC_CONTR = ADC_POWER | ADC_SPEEDLL ;
  61.           Delay(20);                      //ADC power-on delay and Start A/D conversion
  62. }
  63. /*---------------------------- LCD1602相应函数 ---------------------------*/

  64. ///////////////以下为LCD显示数据处理/////////////////
  65. void Num_to_Disp(uchar i, uint Num)
  66. {
  67.         float NUM;
  68.         int xx, yy, zz;
  69.         NUM =(Num * 5/ 1024.0);        //计算公式:10-bit A/D Conversion Result = 1024 x (Vin / Vcc)
  70.         xx = (int)NUM;
  71.         yy = (int)((NUM - (float)(xx)) * 10);
  72.         zz = (int)((NUM - (float)(xx)) * 100)%10;  

  73.         num_char_table[9] = data_char_table[xx / 10];                //电压值十位
  74.         num_char_table[10]= data_char_table[xx % 10];                //电压值个位
  75.         num_char_table[12]= data_char_table[yy];                        //电压值小数点后一位
  76.         num_char_table[13]= data_char_table[zz];                        //电压值小数点后两位?

  77.         pos_char_table[13]= data_char_table[i];                        //当前ADC接口
  78. }
  79. //////////////////以下为LCD显示////////////////////
  80. void LcdDisp(uchar j, uint num)
  81. {
  82.         uint i=0;

  83.         for (i=0;i<16;i++)
  84.         {
  85.                 lcd_char_write(i,0,Lcd_Dis1_table[i]);
  86.                 lcd_char_write(i,1,Lcd_Dis2_table[i]);                  //显示框架
  87.         }
  88.         Num_to_Disp(j, num);
  89.         lcd_char_write(13,0,pos_char_table[13]);
  90.         for(i = 9; i < 14; i++)
  91.         {
  92.                 lcd_char_write(i,1,num_char_table[i]);                  //显示电压
  93.         }                                                                                         
  94.         delay_1ms(100);
  95. }
  96. //////////////以下是LCD1602驱动程序////////////////

  97. void lcd_delay(uchar ms) /*LCD1602 延时*/
  98. {
  99.     uchar j;
  100.     while(ms--){
  101.         for(j=0;j<250;j++)
  102.             {;}
  103.         }   
  104. }

  105. void lcd_busy_wait() /*LCD1602 忙等待*/
  106. {
  107.     lcd_rs_port = 0;
  108.     lcd_rw_port = 1;
  109.     lcd_en_port = 1;
  110.     lcd_data_port = 0xff;
  111.     while (lcd_data_port&0x80);
  112.     lcd_en_port = 0;

  113. }

  114. void lcd_command_write(uint command) /*LCD1602 命令字写入*/
  115. {
  116.     lcd_busy_wait();
  117.     lcd_rs_port = 0;
  118.     lcd_rw_port = 0;
  119.     lcd_en_port = 0;
  120.     lcd_data_port = command;
  121.     lcd_en_port = 1;
  122.     lcd_en_port = 0;     
  123. }

  124. void lcd_system_reset() /*LCD1602 初始化*/
  125. {
  126.     lcd_delay(20);
  127.     lcd_command_write(0x38);
  128.     lcd_delay(100);
  129.     lcd_command_write(0x38);
  130.     lcd_delay(50);
  131.     lcd_command_write(0x38);
  132.     lcd_delay(10);
  133.     lcd_command_write(0x08);
  134.     lcd_command_write(0x01);
  135.     lcd_command_write(0x06);
  136.     lcd_command_write(0x0c);
  137. }

  138. void lcd_char_write(uint x_pos,y_pos,lcd_dat) /*LCD1602 字符写入*/
  139. {
  140.     x_pos &= 0x0f; /* X位置范围 0~15 */
  141.     y_pos &= 0x01; /* Y位置范围 0~ 1 */
  142.     if(y_pos==1) x_pos += 0x40;
  143.     x_pos += 0x80;
  144.     lcd_command_write(x_pos);
  145.     lcd_busy_wait();
  146.     lcd_rs_port = 1;
  147.     lcd_rw_port = 0;
  148.     lcd_en_port = 0;
  149.     lcd_data_port = lcd_dat;
  150.     lcd_en_port = 1;
  151.     lcd_en_port = 0;
  152. }
  153. void lcd_bad_check() /*LCD1602 坏点检查*/
  154. {
  155.     char i,j;
  156.     for(i=0;i<2;i++){
  157.         for(j=0;j<16;j++) {
  158.             lcd_char_write(j,i,0xff);
  159.             }
  160.         }
  161.     lcd_delay(200);
  162.     lcd_delay(200);
  163.         lcd_delay(200);
  164.         lcd_delay(100);
  165.         lcd_delay(200);
  166.     lcd_command_write(0x01); /* clear lcd disp */
  167. }
  168. //////////////////以上是LCD1602驱动程序////////////////
  169. /*-----------------------------    延时程序    ---------------------------*/                    
  170. void Delay(uint n)                                                                                 
  171. {
  172.           uint x;

  173.           while (n--)
  174.            {
  175.                      x = 500;
  176.                      while (x--);
  177.            }
  178. }  
  179. /*1MS为单位的延时程序*/
  180. void delay_1ms(uchar x)
  181. {
  182.     uchar j;
  183. while(x--)
  184. {
  185.         for(j=0;j<125;j++)
  186.             {;}
  187.     }   
  188. }  

  189. /*****************************************************************
  190. 函数: averageValueVolgate()
  191. 用途: 求多次采集电压平均值
  192. 传入参数:chan是端口号
  193. 返回值:Val_Av是多次采样的电压值平均值  
  194. ******************************************************************/
  195. float averageValueVolgate(uchar chan)
  196. {
  197.         float voltageValue=0;
  198.         uchar num;
  199.         for(num=100;num>0;num--)
  200.         {
  201.                 voltageValue+=GetADCResult(chan);
  202.         }
  203.         voltageValue/=100.0;
  204.         voltageValue=voltageValue*5.0/1024;
  205.         return (voltageValue);
  206. }


  207. /*-------------------------------- 主函数 --------------------------------*/                                             
  208. void main()
  209. {
  210.                 uchar i;
  211.                 lcd_system_reset();                                                   //LCD1602 初始化
  212.                 lcd_bad_check();                                                           //LCD1602 坏点检查
  213.         InitADC();                                      //初始化ADC特殊功能寄存器
  214.         //        P1M1 = 0xFF;                                         //P1.0/P1.5高阻 0011 1111
  215.       //  P1M0 = 0x00;                                         //P1.0/P1.5高阻 0000 0000
  216.         while (1)
  217.      {         
  218.          i = 0;
  219.          LcdDisp(i,averageValueVolgate(0));      //液晶1602显示第3通道电压值
  220.          Delay(1000);
  221.      }                        
  222. }
复制代码


评分

参与人数 1黑币 +10 收起 理由
cciejs12345 + 10

查看全部评分

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

使用道具 举报

沙发
ID:309126 发表于 2018-5-17 21:23 | 只看该作者
这是液晶显示的结果

777.JPG (1.72 MB, 下载次数: 31)

777.JPG
回复

使用道具 举报

板凳
ID:309126 发表于 2018-5-18 14:46 | 只看该作者
没人吗
回复

使用道具 举报

地板
ID:213173 发表于 2018-5-18 21:11 | 只看该作者

见前贴《关于STC12C5A60S2单片机AD采样电压跳动不准的问题》的回复。
回复

使用道具 举报

5#
ID:208262 发表于 2018-5-19 11:40 | 只看该作者
怎么回复这么多,还没有明白呢,前面的回答可以的
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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