找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索

使用STC12单片机实现8路AD检测程序

查看数: 3950 | 评论数: 6 | 收藏 5
关灯 | 提示:支持键盘翻页<-左 右->
    组图打开中,请稍候......
发布时间: 2020-12-16 23:59

正文摘要:

目前程序能够实现8路AD检测数据但是显示有问题,并且使用按键进行切换时总会不知道跳到什么地方去。          /* 功能:使用12C5A60S2内部AD读取外部8 路电压,显示在1602上 */ /*&n ...

回复

ID:213173 发表于 2024-3-10 21:21
本帖最后由 wulin 于 2024-3-11 06:02 编辑
jony1122 发表于 2024-3-10 17:12
老师你好,我将LCD屏的接口改成以下三个,屏幕上不显示数据。
我系统板的LCD的数据接口在P0,还要改哪个 ...

软件都是基于硬件条件编写的,同一品牌的MCU不同型号的某功能也不见得相同,不可以生搬硬套。
ID:1045846 发表于 2024-3-10 17:12
wulin 发表于 2020-12-17 14:45
给你改写成了ADC查询方式,如果硬件没有错误应该可以直接用于你的实验板。

老师你好,我将LCD屏的接口改成以下三个,屏幕上不显示数据。
我系统板的LCD的数据接口在P0,还要改哪个地方,才能显示数据,谢谢。
sbit LCD_RS=P2^5;                                        //液晶屏RS口  写指令低,写数据高
sbit LCD_RW=P2^6;                                        //液晶屏RW口  写数据低,读数据高 如果不查忙RW可以直接接地,去掉LCD_RW=0;
sbit LCD_EN=P2^7;                                        //液晶屏EN口  高电平使能,低跳变执行
ID:213173 发表于 2020-12-17 14:45
me262c919 发表于 2020-12-17 00:01
显示无法显示小数,一直是LCD一直是闪烁的,望大神指点

给你改写成了ADC查询方式,如果硬件没有错误应该可以直接用于你的实验板。
  1. #include <STC12C5A60S2.H>
  2. #include <intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. /***宏定义ADC的操作命令***/
  6. #define ADC_POWER   0x80            //ADC power control bit
  7. #define ADC_FLAG    0x10            //ADC complete flag
  8. #define ADC_START   0x08            //ADC start control bit
  9. #define ADC_SPEEDLL 0x00            //420 clocks
  10. /***LCD端口定义***/
  11. //#define DataPort P2                           //连接1602数据口 P2
  12. sbit LCD_RS=P0^7;                                        //液晶屏RS口  写指令低,写数据高
  13. sbit LCD_RW=P0^6;                                        //液晶屏RW口  写数据低,读数据高 如果不查忙RW可以直接接地,去掉LCD_RW=0;
  14. sbit LCD_EN=P0^5;                                        //液晶屏EN口  高电平使能,低跳变执行
  15. /********本地全局变量声明**************/
  16. uchar table1[]="Voltmeter No.1";        //LCD第一行字符
  17. uchar table2[]="CH0: 0.000 V";        //LCD第二行字符
  18. uint  dis_buf[8]; //ADC转换数据缓存
  19. uint  Cnt2ms;                //计时变量
  20. uchar Channel;                //通道变量
  21. uchar num=0;                //轮流显示变量
  22. uint  ADC_V;                //ADC电压值变量
  23. /********本地函数声明**************/
  24. void Timer0Init();                                //定时器初始化函数
  25. void InitADC();                                        //ADC初始化函数
  26. uint GetADCResult(uchar ch);        //ADC转换函数
  27. void delay(uint x);                                //延时函数
  28. void write_com(uchar com);                //LCD写命令函数
  29. void write_date(uchar date);        //LCD写数据函数
  30. void LCD_init();                                        //初始化LCD函数
  31. void Filter();                                                //采样滤波函数

  32. void main()
  33. {
  34.         uchar a;
  35.         P1M0=0x00;                        //P1口全部为高阻输入
  36.         P1M1=0xff;                        //P1口全部为高阻输入
  37.         Timer0Init();                //初始化定时器
  38.         InitADC();                   //初始化ADC
  39.         LCD_init();                        //初始化LCD
  40.         write_com(0x80+1);//初始化LCD第一行字符
  41.         for(a=0;a<14;a++)       
  42.                 write_date(table1[a]);
  43.         write_com(0xc0+2);//初始化LCD第二行字符
  44.         for(a=0;a<12;a++)
  45.                 write_date(table2[a]);
  46.         while(1)
  47.         {
  48.                 if(TF0)                        //查询2msT0中断请求标志
  49.                 {
  50.                         TF0=0;                //清除T0中断请求标志
  51.                         Filter();        //读取ADC转换数据
  52.                         Cnt2ms++;
  53.                         if(Cnt2ms>=500)//1秒刷新LCD显示数据
  54.                         {
  55.                                 Cnt2ms=0;
  56.                                 //轮流取缓存中数据强制转换数据类型(32位)运算,得到(4舍5入)mV,显示在LCD
  57.                                 ADC_V=(5*(long)dis_buf[num]*10000/1024+5)/10;//
  58.                                 table2[5]=ADC_V/1000%10+'0';
  59.                                 table2[7]=ADC_V/100%10+'0';
  60.                                 table2[8]=ADC_V/10%10+'0';
  61.                                 table2[9]=ADC_V%10+'0';
  62.                                 write_com(0xc0+4);                        //显示通道数
  63.                                         write_date(num+1+'0');
  64.                                 write_com(0xc0+7);                        //显示电压值
  65.                                 for(a=0;a<5;a++)
  66.                                         write_date(table2[a+5]);
  67.                                 num++;
  68.                                 if(num>=8)
  69.                                         num=0;
  70.                         }
  71.                 }
  72.         }
  73. }
  74. /*******1ms延时程序********/
  75. void delay(uint x)//1T/11.0592MHz
  76. {
  77.         uint a,b;
  78.         for(a=x;a>0;a--)
  79.                 for(b=829;b>0;b--);
  80. }
  81. /*******1602液晶屏写指令程序********/
  82. void write_com(uchar com)
  83. {
  84.         LCD_RS=0;        //允许写指令
  85.         P2=com;                //传递指令
  86.         delay(1);        //延时1ms
  87.         LCD_EN=1;        //使能写入
  88.         delay(1);        //延时1ms
  89.         LCD_EN=0;        //低跳变执行
  90.        
  91. }
  92. /*******1602液晶屏写数据程序********/
  93. void write_date(uchar date)
  94. {
  95.         LCD_RS=1;        //允许写数据
  96.         P2 =date;        //传递数据
  97.         delay(1);        //延时1ms
  98.         LCD_EN=1;        //使能写入
  99.         delay(1);        //延时1ms
  100.         LCD_EN=0;        //低跳变执行
  101.        
  102. }
  103. /*******1602液晶屏初始化程序********/
  104. void LCD_init()                //设置显示模式、
  105. {
  106.         LCD_RW=0;
  107.         LCD_EN=0;                //初始设置LCD_EN低电平
  108.         write_com(0x38);//设置16*2显示,5*7点阵,8位数据接口
  109.         write_com(0x01);//显示清零,数据指针清零
  110.         write_com(0x0c);//设置开显示,不显光标
  111.         write_com(0x06);//设置写一个字符后地址指针加1
  112. }
  113. /*----------------------------
  114.         Init Timer0
  115. ----------------------------*/
  116. void Timer0Init()                //2毫秒@11.0592MHz
  117. {
  118.         AUXR |= 0x80;                //定时器时钟1T模式
  119.         TMOD &= 0xF0;                //设置定时器模式
  120.         TL0 = 0x9A;                        //设置定时初值
  121.         TH0 = 0xA9;                        //设置定时初值
  122.         TF0 = 0;                        //清除TF0标志
  123.         TR0 = 1;                        //定时器0开始计时
  124. }
  125. /*----------------------------
  126. Get ADC result
  127. ----------------------------*/
  128. uint GetADCResult(uchar ch)
  129. {
  130.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
  131.         _nop_();                        //Must wait before inquiry
  132.         _nop_();
  133.         _nop_();
  134.         _nop_();
  135.         while (!(ADC_CONTR & ADC_FLAG));//Wait complete flag
  136.         ADC_CONTR &= ~ADC_FLAG;         //Close ADC
  137.         return (ADC_RES<<2|ADC_RESL);    //返回10位ADC
  138. }
  139. /*----------------------------
  140. Initial ADC sfr
  141. ----------------------------*/
  142. void InitADC()
  143. {
  144.         P1ASF = 0xff;                   //Open 8 channels ADC function
  145.         ADC_RES = 0;                    //Clear previous result
  146.         ADC_RESL= 0;
  147.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
  148.         delay(2);        //延时2ms            //ADC power-on and delay
  149. }
  150. //采样滤波
  151. void Filter()
  152. {
  153.         static uchar count=0;
  154.         static uint V_ADC;
  155.         V_ADC+=GetADCResult(Channel);
  156.         count++;
  157.         if(count>=10)                                //如果计数十次采样
  158.         {
  159.                 count=0;                                        //计数器清0
  160.                 dis_buf[Channel]=(V_ADC+5)/10;//四舍五入获取平均值保存在缓存中
  161.                 V_ADC=0;                                        //采样变量清0
  162.                 Channel++;
  163.                 if(Channel==8)
  164.                         Channel=0;
  165.         }
  166. }
复制代码



ID:213173 发表于 2020-12-17 08:33
楼主这程序写得也太啰嗦,而且还有不少错误。不如把STC官方示例稍改一下,串口显示改LCD显示即可。
  1. /***************************************************************/
  2. /*------------------------------------------------------------------*/
  3. /* --- STC MCU Limited ---------------------------------------------*/
  4. /* --- STC12C5Axx Series MCU A/D Conversion Demo -------------------*/

  5. /* If you want to use the program or the program referenced in the  */
  6. /* article, please specify in which data and procedures from STC    */
  7. /*------------------------------------------------------------------*/

  8. #include "reg51.h"
  9. #include "intrins.h"

  10. #define FOSC    11059200L
  11. #define BAUD    9600

  12. typedef unsigned char BYTE;
  13. typedef unsigned int WORD;

  14. /*Declare SFR associated with the ADC */
  15. sfr ADC_CONTR   =   0xBC;           //ADC control register
  16. sfr ADC_RES     =   0xBD;           //ADC hight 8-bit result register
  17. sfr ADC_LOW2    =   0xBE;           //ADC low 2-bit result register
  18. sfr P1ASF       =   0x9D;           //P1 secondary function control register

  19. /*Define ADC operation const for ADC_CONTR*/
  20. #define ADC_POWER   0x80            //ADC power control bit
  21. #define ADC_FLAG    0x10            //ADC complete flag
  22. #define ADC_START   0x08            //ADC start control bit
  23. #define ADC_SPEEDLL 0x00            //420 clocks
  24. #define ADC_SPEEDL  0x20            //280 clocks
  25. #define ADC_SPEEDH  0x40            //140 clocks
  26. #define ADC_SPEEDHH 0x60            //70 clocks

  27. void InitUart();
  28. void SendData(BYTE dat);
  29. void Delay(WORD n);
  30. void InitADC();

  31. BYTE ch = 0;                        //ADC channel NO.

  32. void main()
  33. {
  34.     InitUart();                     //Init UART, use to show ADC result
  35.     InitADC();                      //Init ADC sfr
  36.     IE = 0xa0;                      //Enable ADC interrupt and Open master interrupt switch
  37.                                     //Start A/D conversion
  38.     while (1);
  39. }

  40. /*----------------------------
  41. ADC interrupt service routine
  42. ----------------------------*/
  43. void adc_isr() interrupt 5
  44. {
  45.     ADC_CONTR &= !ADC_FLAG;         //Clear ADC interrupt flag

  46.     SendData(ch);                   //Show Channel NO.
  47.     SendData(ADC_RES);              //Get ADC high 8-bit result and Send to UART

  48. //if you want show 10-bit result, uncomment next line
  49. //    SendData(ADC_LOW2);             //Show ADC low 2-bit result
  50.    
  51.     if (++ch > 7) ch = 0;           //switch to next channel
  52.     ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;
  53. }

  54. /*----------------------------
  55. Initial ADC sfr
  56. ----------------------------*/
  57. void InitADC()
  58. {
  59.     P1ASF = 0xff;                   //Set all P1 as analog input port
  60.     ADC_RES = 0;                    //Clear previous result
  61.     ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;
  62.     Delay(2);                       //ADC power-on delay and Start A/D conversion
  63. }

  64. /*----------------------------
  65. Initial UART
  66. ----------------------------*/
  67. void InitUart()
  68. {
  69.     SCON = 0x5a;                    //8 bit data ,no parity bit
  70.     TMOD = 0x20;                    //T1 as 8-bit auto reload
  71.     TH1 = TL1 = -(FOSC/12/32/BAUD); //Set Uart baudrate
  72.     TR1 = 1;                        //T1 start running
  73. }

  74. /*----------------------------
  75. Send one byte data to PC
  76. Input: dat (UART data)
  77. Output:-
  78. ----------------------------*/
  79. void SendData(BYTE dat)
  80. {
  81.     while (!TI);                    //Wait for the previous data is sent
  82.     TI = 0;                         //Clear TI flag
  83.     SBUF = dat;                     //Send current data
  84. }

  85. /*----------------------------
  86. Software delay function
  87. ----------------------------*/
  88. void Delay(WORD n)
  89. {
  90.     WORD x;

  91.     while (n--)
  92.     {
  93.         x = 5000;
  94.         while (x--);
  95.     }
  96. }
复制代码



ID:555216 发表于 2020-12-17 00:43
感谢楼主 受益匪浅
ID:861836 发表于 2020-12-17 00:01
显示无法显示小数,一直是LCD一直是闪烁的,望大神指点

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

Powered by 单片机教程网

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