找回密码
 立即注册
查看: 1599|回复: 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);       
}

回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:135
  • 最近打卡:2024-12-25 10:15:05

47

主题

1350

回帖

8058

积分

荣誉版主

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

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

使用道具 举报 送花

3

主题

19

回帖

135

积分

注册会员

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

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

点评

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

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:135
  • 最近打卡:2024-12-25 10:15:05

47

主题

1350

回帖

8058

积分

荣誉版主

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

积分
8058
QQ
发表于 2023-5-5 11:38:31 | 显示全部楼层
140*** 发表于 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
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-05-02 10:07:51

73

主题

5883

回帖

1万

积分

超级版主

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

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

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2025-05-02 08:32:59

717

主题

1万

回帖

1万

积分

管理员

积分
15617
发表于 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
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-05-02 10:07:51

73

主题

5883

回帖

1万

积分

超级版主

积分
12079
发表于 2023-5-22 23:13:31 | 显示全部楼层
140*** 发表于 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, 2025-5-2 13:05 , Processed in 0.153446 second(s), 115 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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