找回密码
 立即注册

QQ登录

只需一步,快速开始

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

如何将电池电压通过ADC转换显示到液晶屏上?附单片机代码

[复制链接]
跳转到指定楼层
楼主
怎么将电池电压通过AD转换显示到液晶上。液晶屏字模已经显示好。一个液晶初始化代码和ADC转换查询代码东拼西凑组成的程序。显示电压显示0.
芯片型号STC15F2K60S2.输入脚接的P1.7通过两个1K电阻分压


单片机代码如下
#include "REG51.h"
#include "oled.h"
#include "bmp.h"
#include "intrins.h"
sfr ADC_CONTR   =   0xBC;           //ADC控制寄存器
sfr ADC_RES     =   0xBD;           //ADC高8位结果
sfr ADC_LOW2    =   0xBE;           //ADC低2位结果
sfr P1ASF       =   0x9D;           //P1口第2功能控制寄存器

#define ADC_POWER   0x80            //ADC电源控制位
#define ADC_FLAG    0x10            //ADC完成标志
#define ADC_START   0x08            //ADC起始控制位
#define ADC_SPEEDLL 0x00            //540个时钟
#define ADC_SPEEDL  0x20            //360个时钟
#define ADC_SPEEDH  0x40            //180个时钟
#define ADC_SPEEDHH 0x60            //90个时钟

void InitADC();//初始化ADC
typedef unsigned char BYTE;//串口通道名称声明
BYTE ch = 7;                        //ADC通道号
BYTE GetADCResult(BYTE ch);//读取adc结果
void ShowResult(BYTE ch);
void nem(BYTE dat);

int main(void)
{        
        Init_ssd1327();
        while(1)
        {
                OLED_ShowChinese(0,48,0,16);
                OLED_ShowChinese(16,48,1,16);
                OLED_ShowNum(40,36,nem,4,32);
                OLED_ShowString(112,36,"V",32);
                delay_ms(1000);
                ShowResult(7);              //显示通道7
        }
}

/*----------------------------
发送ADC结果到液晶显示
----------------------------*/
void ShowResult(BYTE ch)
{
    nem(ch);                   //显示通道号
    nem(GetADCResult(ch));     //显示ADC高8位结果

//    SendData(ADC_LOW2);           //显示低2位结果
}

/*----------------------------
读取ADC结果
----------------------------*/
BYTE GetADCResult(BYTE ch)
{
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
    _nop_();                        //等待4个NOP
    _nop_();
    _nop_();
    _nop_();
    while (!(ADC_CONTR & ADC_FLAG));//等待ADC转换完成
    ADC_CONTR &= ~ADC_FLAG;         //Close ADC

    return ADC_RES;                 //返回ADC结果
}

/*----------------------------
初始化ADC
----------------------------*/
void InitADC()
{
    P1ASF = 0xff;                   //设置P1口为AD口
    ADC_RES = 0;                    //清除结果寄存器
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
    delay_ms(2);                       //ADC上电并延时
}

        

51hei图片20221229113832.jpg (3.33 MB, 下载次数: 93)

OLED接线测试

OLED接线测试

51hei图片20221229114122.png (361.49 KB, 下载次数: 93)

STC15F2K60S2管脚图

STC15F2K60S2管脚图

51hei图片20221229114128.png (158.42 KB, 下载次数: 92)

STC15内部ADC结构

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

使用道具 举报

沙发
ID:301191 发表于 2022-12-30 06:04 | 只看该作者
顶一下
回复

使用道具 举报

板凳
ID:161164 发表于 2022-12-30 09:17 | 只看该作者
这代码编译时没报错吗?
nem是什么gui??
回复

使用道具 举报

地板
ID:190152 发表于 2022-12-30 11:03 来自手机 | 只看该作者
lkc8210 发表于 2022-12-30 09:17
这代码编译时没报错吗?
nem是什么gui??

报了几个错,被我解决了。nem是我想显示的电压数值
回复

使用道具 举报

5#
ID:161164 发表于 2022-12-30 11:39 | 只看该作者
高低都不调 发表于 2022-12-30 11:03
报了几个错,被我解决了。nem是我想显示的电压数值

为啥不把新代码贴上来?
回复

使用道具 举报

6#
ID:190152 发表于 2022-12-30 11:48 来自手机 | 只看该作者
lkc8210 发表于 2022-12-30 11:39
为啥不把新代码贴上来?

这个代码就是改好的,编译器可以通过编译就是不知道哪里错了显示屏不显示电压值
回复

使用道具 举报

7#
ID:213173 发表于 2022-12-30 15:06 | 只看该作者
高低都不调 发表于 2022-12-30 11:48
这个代码就是改好的,编译器可以通过编译就是不知道哪里错了显示屏不显示电压值

ADC转换结果不是电压,还要通过公式计算才能得到电压值。模拟信号输入端口要设置高阻模式。
  1. /*----------------------------
  2. 发送ADC结果到液晶显示
  3. ----------------------------*/
  4. void ShowResult(BYTE ch)
  5. {
  6.         unsigned int mV;
  7.         unsigned char temp;
  8.     nem(ch);                   //显示通道号
  9.         temp=GetADCResult(ch);
  10.         //毫伏=(参考电压VCC*八位ADC结果*1000/256)*分压比
  11.         mV=5*(long)temp*1000/256*2;
  12.         nem(mV);     //显示电压毫伏
  13. }
  14. /*----------------------------
  15. 初始化ADC
  16. ----------------------------*/
  17. void InitADC()
  18. {
  19.         P1M0 = 0x80;                                         //设置P1.7高阻 1000 0000
  20.         P1M1 = 0x00;
  21.     P1ASF = 0x80;                   //设置P1.7口为模拟输入
  22.     ADC_RES = 0;                    //清除结果寄存器
  23.     ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
  24.     delay_ms(2);                       //ADC上电并延时
  25. }
  26. /*----------------------------
  27. 读取ADC结果
  28. ----------------------------*/
  29. BYTE GetADCResult(BYTE ch)
  30. {
  31.     ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
  32.     _nop_();                        //等待4个NOP
  33.     _nop_();
  34.     _nop_();
  35.     _nop_();
  36.     while (!(ADC_CONTR & ADC_FLAG));//等待ADC转换完成
  37.     ADC_CONTR &= ~ADC_FLAG;         //Close ADC
  38.     return ADC_RES;                 //返回8位ADC结果
  39. }
复制代码

回复

使用道具 举报

8#
ID:190152 发表于 2022-12-31 13:56 | 只看该作者
感谢各位热情回答修改好的代码液晶上成功显示电压3866mv 电脑串口也可以同时显示AD转换值


//本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
//若无特别说明,工作频率一般为11.0592MHz


#include "reg51.h"
#include "intrins.h"
#include "oled.h"
#include "bmp.h"

#define FOSC    11059200L
#define BAUD    115200

typedef unsigned char BYTE;
typedef unsigned int WORD;

#define     URMD    0           //0:使用定时器2作为波特率发生器
                                //1:使用定时器1的模式0(16位自动重载模式)作为波特率发生器
                                //2:使用定时器1的模式2(8位自动重载模式)作为波特率发生器

sfr T2H   = 0xd6;               //定时器2高8位
sfr T2L   = 0xd7;               //定时器2低8位

sfr P1M1 = 0x91;    //PxM1.n,PxM0.n     =00--->Standard,    01--->push-pull
sfr P1M0 = 0x92;    //                  =10--->pure input,  11--->open drain
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xB1;
sfr P3M0 = 0xB2;
sfr P4M1 = 0xB3;
sfr P4M0 = 0xB4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P6M1 = 0xCB;
sfr P6M0 = 0xCC;
sfr P7M1 = 0xE1;
sfr P7M0 = 0xE2;

sfr  AUXR       =   0x8e;       //辅助寄存器                              

sfr ADC_CONTR   =   0xBC;           //ADC控制寄存器
sfr ADC_RES     =   0xBD;           //ADC高8位结果
sfr ADC_LOW2    =   0xBE;           //ADC低2位结果
sfr P1ASF       =   0x9D;           //P1口第2功能控制寄存器

#define ADC_POWER   0x80            //ADC电源控制位
#define ADC_FLAG    0x10            //ADC完成标志
#define ADC_START   0x08            //ADC起始控制位
#define ADC_SPEEDLL 0x00            //540个时钟
#define ADC_SPEEDL  0x20            //360个时钟
#define ADC_SPEEDH  0x40            //180个时钟
#define ADC_SPEEDHH 0x60            //90个时钟

void InitUart();
void InitADC();
void SendData(BYTE dat);
BYTE GetADCResult(BYTE ch);
void Delay(WORD n);
void ShowResult(BYTE ch);
unsigned int num;//AD转换数据缓存
unsigned int mV;//AD电压显示数字毫伏
ch=7;

void main()
{
    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x80;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;
    P6M0 = 0x00;
    P6M1 = 0x00;
    P7M0 = 0x00;
    P7M1 = 0x00;

    InitUart();                     //初始化串口
    InitADC();                      //初始化ADC
        Init_ssd1327();                 //初始化OLED液晶驱动
    while (1)
    {
        ShowResult(7);              //显示通道7
                OLED_ShowChinese(0,48,0,16);
                OLED_ShowChinese(16,48,1,16);
                OLED_ShowNum(40,36,num,4,32);
                OLED_ShowString(112,48,"mV",16);
                num=5*(long)ADC_RES*1000/256*2;
    }
}

/*----------------------------
发送ADC结果到PC
----------------------------*/
void ShowResult(BYTE ch)
{
    SendData(ch);                   //显示通道号
    SendData(GetADCResult(ch));     //显示ADC高8位结果

//    SendData(ADC_LOW2);           //显示低2位结果
}

/*----------------------------
读取ADC结果
----------------------------*/
BYTE GetADCResult(BYTE ch)
{
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
    _nop_();                        //等待4个NOP
    _nop_();
    _nop_();
    _nop_();
    while (!(ADC_CONTR & ADC_FLAG));//等待ADC转换完成
    ADC_CONTR &= ~ADC_FLAG;         //Close ADC

    return ADC_RES;                 //返回ADC结果
}

/*----------------------------
初始化串口
----------------------------*/
void InitUart()
{
    SCON = 0x5a;                //设置串口为8位可变波特率
#if URMD == 0
    T2L = (65536 - (FOSC/4/BAUD));
    T2H = (65536 - (FOSC/4/BAUD)) >> 8;
    AUXR = 0x14;                //T2为1T模式, 并启动定时器2
    AUXR |= 0x01;               //选择定时器2为串口1的波特率发生器
#elif URMD == 1
    AUXR = 0x40;                //定时器1为1T模式
    TMOD = 0x00;                //定时器1为模式0(16位自动重载)
    TL1 = (65536 - (FOSC/4/BAUD));
    TH1 = (65536 - (FOSC/4/BAUD)) >> 8;
    TR1 = 1;                    //定时器1开始启动
#else
    TMOD = 0x20;                //设置定时器1为8位自动重装载模式
    AUXR = 0x40;                //定时器1为1T模式
    TH1 = TL1 = (256 - (FOSC/32/BAUD));
    TR1 = 1;
#endif
}

/*----------------------------
初始化ADC
----------------------------*/
void InitADC()
{
    P1ASF = 0x80;                   //设置P1口为AD口
    ADC_RES = 0;                    //清除结果寄存器
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
    Delay(2);                       //ADC上电并延时
}

/*----------------------------
发送串口数据
----------------------------*/
void SendData(BYTE dat)
{
    while (!TI);                    //等待前一个数据发送完成
    TI = 0;                         //清除发送标志
    SBUF = dat;                     //发送当前数据
}

/*----------------------------
软件延时
----------------------------*/
void Delay(WORD n)
{
    WORD x;

    while (n--)
    {
        x = 5000;
        while (x--);
    }
}

回复

使用道具 举报

9#
ID:227484 发表于 2023-10-28 20:05 | 只看该作者
学习了抽空试一下
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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