_奶咖君_
发表于 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();
}
}