_奶咖君_ 发表于 2024-5-24 15:47:03

Lkck8210 发表于 2024-5-24 15:41
对头!!

那就是你通道切换的时候需要把后四位先清零再赋值。。大概就是这样

ADC_CONTR = (ADC_CONTR & 0xf0) | ADC_START | channel;

Lkck8210 发表于 2024-5-24 16:03:00

_奶咖君_ 发表于 2024-5-24 15:47
那就是你通道切换的时候需要把后四位先清零再赋值。。大概就是这样

ADC_CONTR = (ADC_CONTR & 0xf0) |...

行了~!!
感谢解答{:handshake:}

Lkck8210 发表于 2024-5-24 16:11:34

以下是修改好的代码
#include "reg51.h"
#include "intrins.h"

#include <stdio.h>//printf, sprintf
#include <intrins.h>//_nop_, _cror_, _crol_
typedef         unsigned char        u8;//0 to 255
typedef         unsigned int        u16;//0 to 65535
typedef         unsigned long        u32;//0 to 4294967295
//测试工作频率为11.0592MHz

sfr         AUXR      =         0x8e;
sfr   ADC_CONTR   =   0xbc;
sfr   ADC_RES   =   0xbd;
sfr   ADC_RESL    =   0xbe;
sfr   ADCCFG      =   0xde;

sfr P3M0      =   0xb2;                                       //P3口配置寄存器0
sfr P3M1      =   0xb1;                                       //P3口配置寄存器1
sfr P5M0      =   0xca;                                       //P5口配置寄存器0
sfr P5M1      =   0xc9;                                       //P5口配置寄存器1

bit Busy = 0;
void Uart1_Isr(void) interrupt 4
{
    if (TI)                                //检测串口1发送中断
    {
      TI = 0;                        //清除串口1发送中断请求位
      Busy = 0;
    }
    if (RI)                                //检测串口1接收中断
    {
      RI = 0;                        //清除串口1接收中断请求位
    }
}
u8 putchar(u8 dat)
{
    Busy = 1;
    SBUF = dat;
    while(Busy);
    return dat;
}
void Uart1_Init(void)        //115200bps@11.0592MHz
{
    SCON = 0x50;                //8位数据,可变波特率
    AUXR |= 0x40;                //定时器时钟1T模式
    AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
    TMOD &= 0x0F;                //设置定时器模式
    TL1 = 0xE8;                        //设置定时初始值
    TH1 = 0xFF;                        //设置定时初始值
    ET1 = 0;                        //禁止定时器中断
    TR1 = 1;                        //定时器1开始计时
    ES = 1;                                //使能串口1中断
}
void Delay1000ms(void)        //@11.0592MHz
{
    unsigned char data i, j, k;

    i = 17;
    j = 27;
    k = 112;
    do
    {
      do
      {
            while (--k);
      }
      while (--j);
    }
    while (--i);
}
void Delay1ms(void)        //@11.0592MHz
{
    unsigned char data i, j;

    i = 15;
    j = 90;
    do
    {
      while (--j);
    }
    while (--i);
}
u16 ADC_Sel(u8 ch)
{
    u16 Temp;
    ADC_CONTR |= 0x40 | ch;                      //启动AD转换
    _nop_();
    _nop_();
    while (!(ADC_CONTR & 0x20));            //查询ADC完成标志
    ADC_CONTR &= ~0x2F;                     //清完成标志及频道选择
    Temp = ADC_RES;                           //读取ADC结果
    Temp = Temp<<8 | ADC_RESL;
    return Temp;
}
u16 Temp;
u16 Cnt = 0;
void main()
{
    P3M0 = 0x00;
    P3M1 = 0x0c;
    P5M0 = 0x00;
    P5M1 = 0x10;

    ADCCFG = 0x2f;                              //设置ADC时钟为系统时钟/2/16/16
    Uart1_Init();
    EA=1;
    ADC_CONTR = 0x82;                           //使能ADC模块
    Delay1ms();
    while (1)
    {
      Cnt++;
      printf("ADC Test: %u\r\n",Cnt);
      Delay1ms();
      Temp = ADC_Sel(2);
      printf("P32 Raw: %u\r\n",Temp);
      printf("P32 Volt: %lu x10mV\r\n",(u32)Temp*500/1024);
      Delay1ms();
      Temp = ADC_Sel(3);
      printf("P33 Raw: %u\r\n",Temp);
      printf("P33 Volt: %lu x10mV\r\n",(u32)Temp*500/1024);
      Delay1ms();
      Temp = ADC_Sel(4);
      printf("P54 Raw: %u\r\n",Temp);
      printf("P54 Volt: %lu x10mV\r\n",(u32)Temp*500/1024);
      Delay1000ms();
    }
}

_奶咖君_ 发表于 2024-5-24 16:19:44

Lkck8210 发表于 2024-5-24 16:11
以下是修改好的代码

{:4_250:}{:4_250:}

梁工 发表于 2024-5-24 17:04:03

Lkck8210 发表于 2024-5-24 15:46
然后呢?

什么然后呢?   你要问什么?能不能多打几个字啊?

Lkck8210 发表于 2024-5-24 17:23:26

梁工 发表于 2024-5-24 17:04
什么然后呢?   你要问什么?能不能多打几个字啊?

我要问的就是贴子的标题和1楼的内容
但梁工你只是贴一个例程注释
然后附上一个附件
你甚至连一个字都没打{:4_167:}



21cnsound 发表于 2024-5-24 17:45:11

本帖最后由 21cnsound 于 2024-5-24 18:00 编辑

Lkck8210 发表于 2024-5-24 16:11
以下是修改好的代码
看了下,其实就是改了清完成标志及频道选择,把~0x20改成了~0x2F,而~0x20更为合理吧,把通道号指向内部通道,主要是修改这个不影响测试结果吧
ADC_CONTR &= ~0x2F;                     //清完成标志及频道选择

梁工 发表于 2024-5-24 18:36:58

Lkck8210 发表于 2024-5-24 17:23
我要问的就是贴子的标题和1楼的内容
但梁工你只是贴一个例程注释
然后附上一个附件


你1楼说的:ADC读不到电压。
于是,我贴了我的程序,我拷贝程序里的详细说明,那也是我编程时一个一个字打上去的,难道我还要再一个一个字再打一遍么?拷贝不是更快?
你说ADC读不到电压,我专门发了8脚的程序让你测试下,好像你只测了ADC15计算VCC的程序,并且正常了,你贴了一个图,没有任何说明,就发了一个“然后呢?” 我就不明白你要表达什么。

Lkck8210 发表于 2024-5-24 23:27:08

21cnsound 发表于 2024-5-24 17:45
看了下,其实就是改了清完成标志及频道选择,把~0x20改成了~0x2F,而~0x20更为合理吧,把通道号指向内部通 ...

对,这样写好像有问题
我会再更新一下代码

Lkck8210 发表于 2024-5-24 23:28:32

最终版本
#include "reg51.h"
#include "intrins.h"

#include <stdio.h>//printf, sprintf
#include <intrins.h>//_nop_, _cror_, _crol_
typedef         unsigned char      u8;//0 to 255
typedef         unsigned int      u16;//0 to 65535
typedef         unsigned long      u32;//0 to 4294967295
//测试工作频率为11.0592MHz

sfr         AUXR      =         0x8e;
sfr   ADC_CONTR   =   0xbc;
sfr   ADC_RES   =   0xbd;
sfr   ADC_RESL    =   0xbe;
sfr   ADCCFG      =   0xde;

sfr P3M0      =   0xb2;                                       //P3口配置寄存器0
sfr P3M1      =   0xb1;                                       //P3口配置寄存器1
sfr P5M0      =   0xca;                                       //P5口配置寄存器0
sfr P5M1      =   0xc9;                                       //P5口配置寄存器1

bit Busy = 0;
void Uart1_Isr(void) interrupt 4
{
    if (TI)                              //检测串口1发送中断
    {
      TI = 0;                        //清除串口1发送中断请求位
      Busy = 0;
    }
    if (RI)                              //检测串口1接收中断
    {
      RI = 0;                        //清除串口1接收中断请求位
    }
}
u8 putchar(u8 dat)
{
    Busy = 1;
    SBUF = dat;
    while(Busy);
    return dat;
}
void Uart1_Init(void)      //115200bps@11.0592MHz
{
    SCON = 0x50;                //8位数据,可变波特率
    AUXR |= 0x40;                //定时器时钟1T模式
    AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
    TMOD &= 0x0F;                //设置定时器模式
    TL1 = 0xE8;                        //设置定时初始值
    TH1 = 0xFF;                        //设置定时初始值
    ET1 = 0;                        //禁止定时器中断
    TR1 = 1;                        //定时器1开始计时
    ES = 1;                              //使能串口1中断
}
void Delay1000ms(void)      //@11.0592MHz
{
    unsigned char data i, j, k;

    i = 17;
    j = 27;
    k = 112;
    do
    {
      do
      {
            while (--k);
      }
      while (--j);
    }
    while (--i);
}
void Delay1ms(void)      //@11.0592MHz
{
    unsigned char data i, j;

    i = 15;
    j = 90;
    do
    {
      while (--j);
    }
    while (--i);
}
u16 ADC_Sel(u8 ch)
{
    u16 Temp;
        ADC_CONTR &= 0xF0;
    ADC_CONTR |= 0x40 | ch;                      //启动AD转换
    _nop_();
    _nop_();
    while (!(ADC_CONTR & 0x20));            //查询ADC完成标志
    ADC_CONTR &= ~0x20;                     //清完成标志
    Temp = ADC_RES;                           //读取ADC结果
    Temp = Temp<<8 | ADC_RESL;
    return Temp;
}
u16 Temp;
u16 Cnt = 0;
void main()
{
    P3M0 = 0x00;
    P3M1 = 0x0c;
    P5M0 = 0x00;
    P5M1 = 0x10;

    ADCCFG = 0x2f;                              //设置ADC时钟为系统时钟/2/16/16
    Uart1_Init();
    EA=1;
    ADC_CONTR = 0x82;                           //使能ADC模块
    Delay1ms();
    while (1)
    {
      Cnt++;
      printf("ADC Test: %u\r\n",Cnt);
      Delay1ms();
      Temp = ADC_Sel(2);
      printf("P32 Raw: %u\r\n",Temp);
      printf("P32 Volt: %lu x10mV\r\n",(u32)Temp*500/1024);
      Delay1ms();
      Temp = ADC_Sel(3);
      printf("P33 Raw: %u\r\n",Temp);
      printf("P33 Volt: %lu x10mV\r\n",(u32)Temp*500/1024);
      Delay1ms();
      Temp = ADC_Sel(4);
      printf("P54 Raw: %u\r\n",Temp);
      printf("P54 Volt: %lu x10mV\r\n",(u32)Temp*500/1024);
      Delay1000ms();
    }
}

页: 1 [2] 3
查看完整版本: ADC 读不到电压 | 已解决