前行者 发表于 2024-5-19 15:19:57

sc15w单片机ADC调不出来10位

sc15w408as用例程里的程序,设置的是10位的,为啥显示是8位的。





u16        Get_ADC10bitResult(u8 channel)        //channel = 0~7
{
        u16        adc;
        u8        i;

        if(channel > ADC_CH7)        return        1024;        //错误,返回1024,调用的程序判断       
        ADC_RES = 0;
        ADC_RESL = 0;

        ADC_CONTR = (ADC_CONTR & 0xe0) | ADC_START | channel;
        NOP(4);                        //对ADC_CONTR操作后要4T之后才能访问

        for(i=0; i<250; i++)                //超时
        {
                if(ADC_CONTR & ADC_FLAG)
                {
                        ADC_CONTR &= ~ADC_FLAG;
                        if(PCON2 &(1<<5))                //10位AD结果的高2位放ADC_RES的低2位,低8位在ADC_RESL。
                        {
                                adc = (u16)(ADC_RES & 3);
                                adc = (adc << 8) | ADC_RESL;
                        }
                        else                //10位AD结果的高8位放ADC_RES,低2位在ADC_RESL的低2位。
                        {
                                adc = (u16)ADC_RES;
                                adc = (adc << 2) | (ADC_RESL & 3);
                        }
                        return        adc;
                }
        }
        return        1024;        //错误,返回1024,调用的程序判断
}


神农鼎 发表于 2024-5-19 15:25:43

要10位ADC, 改用 STC15H2K64S4, STC8G1K08

前行者 发表于 2024-5-19 16:49:52

sc15w408as这个型号的没没有10位么?

神农鼎 发表于 2024-5-19 17:57:34

要10位ADC,
改用【 STC15H2K64S4, STC8G1K08】,
是真10位 ADC

早期的 STC15W系列的ADC 没到这水平

Yim_Hom 发表于 2024-5-19 18:36:24

如果是STC15的话,试试这样写

/**************************************
功能描述:ADC口初始化
入口参数:无
返回值:无
***************************************/
void ADC_config(void)
{
    ADC_CONTR|=0x80;      //开AD转换电源
    Delay_ms(10);         //适当延时等待AD转换供电稳定
    P1ASF|=0x01;            //选择P1.0作为模拟功能AD使用
    ADC_CONTR|=0x00;      //选择P1.0作为AD转换通道输入使用
    ADC_CONTR|=0x60;      //AD转换速度为90个时钟周期转换一次
    ADC_CONTR&=0xEF;      //清AD转换完成标志
    EADC=0;               //禁止ADC转换中断
    CLK_DIV|=0x20;          //ADC转换结果ADC_RES存高2位,ADC_RESL存低8位
    ADC_CONTR|=0x08;      //启动AD转换,ADC_START=1
}

/**************************************
功能描述:ADC口检测AD转换值函数
入口参数:无
返回值:ADC 10位数据
***************************************/
u16 Get_ADC10bitResult(void)
{
    u16 AD_Dat=0;
    ADC_CONTR&=0xEF;         // 将ADC_FLAG清0
    //10位AD结果的高2位放ADC_RES的低2位,低8位在ADC_RESL
    AD_Dat = ADC_RES;          //将ADC_RES低2位移到应在的第9位和第10位
    AD_Dat <<= 8;
    AD_Dat|= ADC_RESL;         //将ADC_RESL的8位移到应在的低8位
    ADC_CONTR|=0x08;         //重新启动AD转换,ADC_START=1。
    return AD_Dat;
}

前行者 发表于 2024-5-19 18:50:26

Yim_Hom 发表于 2024-5-19 18:36
如果是STC15的话,试试这样写

/**************************************


谢谢,我试一下

Yim_Hom 发表于 2024-5-19 19:04:53

前行者 发表于 2024-5-19 18:50
谢谢,我试一下

客气,如果不熟的话,可以先用一种移位方式,能读出来10位AD,说明成功了,然后再用另一种移位方式读成功。如果两种方式都可以了,再去if。。。else。。。选择移位方式。

神农鼎 发表于 2024-5-19 19:15:46





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


#include "reg51.h"
#include "intrins.h"

#define FOSC    11059200UL
#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;

sfrAUXR       =   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_SPEEDL0x20            //360个时钟
#define ADC_SPEEDH0x40            //180个时钟
#define ADC_SPEEDHH 0x60            //90个时钟

void InitUart();
void SendData(BYTE dat);
void Delay(WORD n);
void InitADC();

BYTE ch = 0;                        //ADC通道号

void main()
{
    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    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
    IE = 0xa0;                      //使能ADC中断
                                    //开始AD转换
    while (1);
}

/*----------------------------
ADC中断服务程序
----------------------------*/
void adc_isr() interrupt 5
{
    ADC_CONTR &= !ADC_FLAG;         //清除ADC中断标志

    SendData(ch);                   //显示通道号
    SendData(ADC_RES);            //读取高8位结果并发送到串口

//    SendData(ADC_LOW2);         //显示低2位结果
   
    if (++ch > 7) ch = 0;         //切换到下一个通道
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;
}

/*----------------------------
初始化ADC
----------------------------*/
void InitADC()
{
    P1ASF = 0xff;                   //设置P1口为AD口
    ADC_RES = 0;                  //清除结果寄存器
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;
    Delay(2);                     //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
}

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

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

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


神农鼎 发表于 2024-5-19 19:17:31

STC15W408AS, T2 做波特率发生器,用串口送出来看下

梁工 发表于 2024-5-21 19:12:22

使用官方例子,直接下载HEX文件测试,串口接收,文本显示:


页: [1]
查看完整版本: sc15w单片机ADC调不出来10位