找回密码
 立即注册
查看: 769|回复: 10

请教,GP2Y1014的ADC寄存器使用是否正确

[复制链接]

该用户从未签到

3

主题

19

回帖

135

积分

注册会员

积分
135
发表于 2023-5-4 11:00:23 | 显示全部楼层 |阅读模式
#include <STC32G.h>
#include <intrins.h>
#include <stdio.h>

typedef unsigned char        u8;
typedef unsigned int        u16;
typedef unsigned long        u32;

#define MAIN_Fosc     12000000UL
#define Baudrate      115200L
#define TM            (65536 -(MAIN_Fosc/Baudrate/4))
#define PrintUart     1

sbit LED = P1^1;

u16 AM_PM;

//unsigned char PM25_value;
       
void delay_ms(unsigned int ms);

u16  Get_ADC12bitResult(u8 channel); //channel = 0~15
//u16         PM25_Get_Value(u8 ch);         //获取PM2.5数值

/*串口初始化*/
void UartInit(void)
{
#if(PrintUart == 1)
        SCON = (SCON & 0x3f) | 0x40;
        T1x12 = 1;          //定时器时钟1T模式
        S1BRT = 0;          //串口1选择定时器1为波特率发生器
        TL1  = TM;
        TH1  = TM>>8;
        TR1 = 1;                                //定时器1开始计时
#else
        S2_S = 1;       //UART2 switch to: 0: P1.0 P1.1,  1: P4.6 P4.7
  S2CFG |= 0x01;  //使用串口2时,W1位必需设置为1,否则可能会产生不可预期的错误
        S2CON = (S2CON & 0x3f) | 0x40;
        T2L  = TM;
        T2H  = TM>>8;
        AUXR |= 0x14;              //定时器2时钟1T模式,开始计时
#endif
}

void UartPutc(unsigned char dat)
{
#if(PrintUart == 1)
        SBUF = dat;
        while(TI==0);
        TI = 0;
#else
        S2BUF  = dat;
        while(S2TI == 0);
        S2TI = 0;    //Clear Tx flag
#endif
}

char putchar(char c)
{
        UartPutc(c);
        return c;
}

void main()
{
        WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
        EAXFR = 1; //扩展寄存器(XFR)访问使能
        CKCON = 0; //提高访问XRAM速度

        P1M0 = 0x32; P1M1 = 0x30;

                //  ADC初始化
        ADCTIM = 0x3f;      //设置 ADC 内部时序,ADC采样时间建议设最大值
        ADCCFG = 0x2f;      //设置 ADC 转换结果右对齐,时钟为系统时钟/2/16
        ADC_CONTR = 0x81;   //使能 ADC 模块,并选择1通道
        UartInit();

        while(1)
        {
                GetGP2Y();
//                printf("PM2.5:\r\n",PM25_value);
                delay_ms(1000);
        }
}

void delay_ms(unsigned int ms)
{
    unsigned int i;
    do{
        i = MAIN_Fosc / 6000;
        while(--i);   //6T per loop
    }while(--ms);
}

void Delay4us()                //@12.000MHz
{
        unsigned long i;

        _nop_();
        _nop_();
        _nop_();
        i = 10UL;
        while (i) i--;
}

//========================================================================
// 函数: u16 Get_ADC12bitResult(u8 channel)
// 描述: 查询法读一次ADC结果.
// 参数: channel: 选择要转换的ADC.
// 返回: 12位ADC结果.
// 版本: V1.0, 2012-10-22
//========================================================================
u16 Get_ADC12bitResult(u8 channel)  //channel = 0~15
{
    ADC_RES = 0;
    ADC_RESL = 0;

    ADC_CONTR = (ADC_CONTR & 0xf0) | channel; //设置ADC转换通道
    ADC_START = 1;//启动ADC转换
    _nop_();
    _nop_();
    _nop_();
    _nop_();

    while(ADC_FLAG == 0);                  //wait for ADC finish
    ADC_FLAG = 0;                                    //清除ADC结束标志
    return  (((u16)ADC_RES << 8) | ADC_RESL);
}

/****
*******获取PM2.5值函数
*******传入值:adc通道
*******返回值:PM2.5值
*******注意:本函数需要调用adc获取函数
*****/
//u16 PM25_Get_Value(u8 ch)
//{
//   u16 adc_value = 0;                                                        //adc值变量
//   u16 PM_count = 0;                                                         //计数次数值变量
//   u16 PM25_value = 0;                                                        //PM2.5值变量
//   LED = 0;                                                             //PM2.5 LED灯拉低开启
//   delay_ms(0.28);                       
//   adc_value += Get_ADC12bitResult(u8 channel); //获取一次adc值,并累加
//   Delay4us();                                                   //延时40us
//   LED = 1;                                                                    
//   if(++PM_count >= 5)                               //获取5次adc值
//   {
//      PM_count = 0;                      //计数次数清零
//      adc_value = adc_value / 5;         //取5次平均值
//      PM25_value = ((adc_value/255.0)*5*0.17-0.1)*1000;     //计算PM2.5值
//      adc_value = 0;                     //adc值清零
//   }
//   return PM25_value;                    //返回PM2.5值
//}

void GetGP2Y(void)
{
        float pm;
        LED = 0;                                                        //PM2.5 LED灯拉低开启
        delay_ms(0.28);                                                //延时280us
        AD_PM = Get_ADC12bitResult(u8 channel);        //获取一次adc值
        Delay4us();                                                //延时40us
        LED = 1;                                                        //PM2.5 LED灯拉高关闭
        delay_ms();
        pm = 0.17*AD_PM-0.1;                                 //电压-灰尘转换
        printf("%f\n",pm);       
}

回复 送花

使用道具 举报

  • TA的每日心情
    开心
    4 天前
  • 签到天数: 107 天

    [LV.6]常住居民II

    42

    主题

    1028

    回帖

    7100

    积分

    荣誉版主

    冲哥视频教程和各种开源资料QQ交流群884047237,可群

    积分
    7100
    QQ
    发表于 2023-5-5 09:58:17 | 显示全部楼层
    ADC寄存器使用是否正确?这个问题好像问的让人摸不着头脑,你是想说寄存器这样配置之后采集到的adc数值是否正确吗?
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    3

    主题

    19

    回帖

    135

    积分

    注册会员

    积分
    135
     楼主| 发表于 2023-5-5 10:59:53 | 显示全部楼层
    电子DIY小家 发表于 2023-5-5 09:58
    ADC寄存器使用是否正确?这个问题好像问的让人摸不着头脑,你是想说寄存器这样配置之后采集到的adc数值是否 ...

    是的,我想问ADC寄存器这样配置是否正确

    点评

    最简单的办法就是接个电位器,然后直接串口监测adc数值直接看一下就知道了,从0v拧到5v,看看adc数值是不是从0到最大值  详情 回复 发表于 2023-5-5 11:38
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    4 天前
  • 签到天数: 107 天

    [LV.6]常住居民II

    42

    主题

    1028

    回帖

    7100

    积分

    荣誉版主

    冲哥视频教程和各种开源资料QQ交流群884047237,可群

    积分
    7100
    QQ
    发表于 2023-5-5 11:38:31 | 显示全部楼层
    140711 发表于 2023-5-5 10:59
    是的,我想问ADC寄存器这样配置是否正确

    最简单的办法就是接个电位器,然后直接串口监测adc数值直接看一下就知道了,从0v拧到5v,看看adc数值是不是从0到最大值
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    3

    主题

    19

    回帖

    135

    积分

    注册会员

    积分
    135
     楼主| 发表于 2023-5-14 17:49:51 | 显示全部楼层
    哎,我真后悔选这个单片机做毕设

    点评

    赶快换我们的STC32G做毕设。  详情 回复 发表于 2023-5-14 20:04
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    46

    主题

    3124

    回帖

    7049

    积分

    超级版主

    积分
    7049
    发表于 2023-5-14 20:04:09 | 显示全部楼层
    140711 发表于 2023-5-14 17:49
    哎,我真后悔选这个单片机做毕设

    赶快换我们的STC32G做毕设。
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    557

    主题

    9729

    回帖

    1万

    积分

    管理员

    积分
    14220
    发表于 2023-5-14 20:50:16 | 显示全部楼层
    他没上原理图,都不知道他错在硬件还是软件,楼主先上你原理图的PDF,大家才好帮你
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    3

    主题

    19

    回帖

    135

    积分

    注册会员

    积分
    135
     楼主| 发表于 2023-5-22 21:18:24 | 显示全部楼层
    神农鼎 发表于 2023-5-14 20:50
    他没上原理图,都不知道他错在硬件还是软件,楼主先上你原理图的PDF,大家才好帮你 ...

    这是传感器的原理图
    GP2Y原理图.png

    点评

    楼主不管用什么MCU,最关键是要先了解你用的传感器。 GP2Y1014AU是一个粉尘传感器,模拟电压输出,按其手册要求是工作于脉冲方式。 你贴一个STM32的电路,再问STC32的ADC寄存器配置,很多人都不明白你要问是什么,有  详情 回复 发表于 2023-5-22 23:13
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    46

    主题

    3124

    回帖

    7049

    积分

    超级版主

    积分
    7049
    发表于 2023-5-22 23:13:31 | 显示全部楼层
    140711 发表于 2023-5-22 21:18
    这是传感器的原理图

    楼主不管用什么MCU,最关键是要先了解你用的传感器。
    GP2Y1014AU是一个粉尘传感器,模拟电压输出,按其手册要求是工作于脉冲方式。
    你贴一个STM32的电路,再问STC32的ADC寄存器配置,很多人都不明白你要问是什么,有心做工程,总得理一下电路,改成你现在使用的MCU和IO,而不是网上下载一个STM32的电路。
    ADC寄存器配置,可以参考STC的官方例程,或者先测试STC的例程,再添加一点程序达到你的要求。


    特意下了个手册看,按你图中连接,PA1接ADC输入,PA0提供周期10ms、高电平0.32ms的驱动脉冲,则在输出0.28ms就可以开启ADC采样了。
    1.png

    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    3

    主题

    19

    回帖

    135

    积分

    注册会员

    积分
    135
     楼主| 发表于 2023-5-23 10:40:29 | 显示全部楼层
    梁工 发表于 2023-5-22 23:13
    楼主不管用什么MCU,最关键是要先了解你用的传感器。
    GP2Y1014AU是一个粉尘传感器,模拟电压输出,按其手 ...

    我写的代码是这样的,选择P1.0作为ADC读取通道,即传感器OUT口接P1.0,LED接P1.1,然后需要调用ADC寄存器来读取P1.0通道的数据,但是我找的51程序都是外接ADC0832,而STC32G又集成了ADC模块,我就不知道怎么改了
    粉尘模块.png

    点评

    很简单啊,直接测试、使用STC官方的ADC例程即可。 1、用一个定时器做7ms中断,中断中P1.1输出驱动,定时器装载3ms中断。 2、定时器3ms中断中,启动ADC,允许ADC中断。 3、ADC完成,进入ADC中断,读取ADC,P1.1停止驱  详情 回复 发表于 2023-5-23 10:47
    回复 支持 反对 送花

    使用道具 举报

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

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-6-3 08:28 , Processed in 0.072142 second(s), 69 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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