找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3888|回复: 8
打印 上一主题 下一主题
收起左侧

STC15系列单片机ADC函数库的20200208优化版

  [复制链接]
跳转到指定楼层
楼主
ID:691723 发表于 2020-2-10 15:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
参考:STC官网函数库
优点:初始化P1任何端口后,main函数只需要循环调用ADC_Convert()函数即可循环完成所有配置的ADC端口模拟量采集。ADC转换结果放置在Dpj_ZongCunChu[]数组中,用于其他功能取用。
目的:免费共享,互相提升。
先在ADC.c文件中写入以下内容:
#define _ADC_C_                //预定义名称用于ADC.h中

#include        "all.h"                //头文件
#if ADC_EN                        //ADC_EN已在ADC.h中预定义

//========================================================================
// 函数: ADC初始化
// 描述:
// 参数: ADCx: 结构参数,请参考adc.h里的定义.
// 返回: none.
// 版本: V1.0, 2012-10-22
//========================================================================
void        ADC_Inilize(ADC_InitTypeDef *ADCx)
{

        P1ASF = ADCx->ADC_Px;        //配置ADC端口
        ADC_CONTR = (ADC_CONTR & ~ADC_90T) | ADCx->ADC_Speed;                //配置ADC转换器速度
        if(ADCx->ADC_Power == ENABLE)        ADC_CONTR |= ADC_POWER;                //打开ADC转换器电源
        else                                                        ADC_CONTR &= ~ADC_POWER;        //关闭ADC转换器电源
        if(ADCx->ADC_AdjResult == ADC_RES_H2L8)        PCON2 |=  (1<<5);        //10位AD结果的高2位放ADC_RES的低2位,低8位在ADC_RESL。
        else                                                                        PCON2 &= ~(1<<5);        //10位AD结果的高8位放ADC_RES,低2位在ADC_RESL的低2位。
        if(ADCx->ADC_Interrupt == ENABLE)        EADC = 1;                                //中断允许                ENABLE,DISABLE
        else                                                                EADC = 0;
        if(ADCx->ADC_Polity == PolityHigh)        PADC = 1;                                //优先级设置        PolityHigh,PolityLow
        else                                                                PADC = 0;
}


//========================================================================
// 函数: ADC中断函数
// 描述:
// 参数: none.
// 返回: none.
// 版本: V1.0, 2012-10-22
//========================================================================
void ADC_int (void) interrupt ADC_VECTOR
{
        u8 i=0; u16 t=0;
        ADC_CONTR &= ~ADC_FLAG;                //清除中断标志位
        i=ADC_CONTR&0x07;                        //取当前ADC转换的端口
        if(PCON2 & bit_5)                        //高2低8(提取ADC转换结果)
        {        t=ADC_RES & 3;
                t=(t<<8) + ADC_RESL;
        }else                                                //高8低2(提取ADC转换结果)
        {        t=ADC_RES;
                t=(t<<2) + (ADC_RESL&3);
        }
        t=(u32)t*500/1024;        //默认电源电压5V,检测电压乘100倍,保留2个小数点数字
        //ADC各端口转换结果存储到单片机总存储空间
        Dpj_ZongCunChu[Dpj_AdcCunChuAddr+i*2]=t;
        Dpj_ZongCunChu[Dpj_AdcCunChuAddr+i*2+1]=t>>8;
}
/***************************************
ADC转换函数
说明:当前ADC端口转换完成时,循环切换下一个端口转换        
输入:        无
返回值:0---当前ADC通道未转换完成
                1---ADC通道切换成功
                2---错误,无端口ADC转换
***************************************/
u8 ADC_Convert()
{
        u8 i=0,j=0,k=0;
        if(P1ASF==0) return 2;
        if( (ADC_CONTR&ADC_START)==0 )        //判断ADC空闲
        {        i=ADC_CONTR&0x07;        //提取当前ADC转换通道号
                if((++i)>=8)i=0;        //判断指向下一通道越界,从新从0通道查询
                j=8+i;
                for(;i<j;i++)                //轮流查询8个ADC通道允许状态
                {        if(i<8)        k=i;
                        else        k=i-8;
                        if(P1ASF&(1<<k))//判断bit.k位被设置为ADC转换端口
                        {        ADC_CONTR&=~0x07;                //清除ADC通道端口
                                ADC_CONTR=ADC_CONTR|k;        //配置下一个允许ADC转换的通道
                                ADC_CONTR|=ADC_START;        //启动ADC转换
                                return 1;
                        }
                }
        }
        return 0;
}
#endif

以下为ADC.h文件内容:

#ifndef        __ADC_H
#define        __ADC_H

#ifdef _ADC_C_
#define ADC_EXT
#else
#define ADC_EXT extern
#endif

//宏定义延时文件是否编译;0----不编译;1----编译
#define ADC_EN        1
#if ADC_EN

#define        ADC_P10                0x01        //IO引脚 Px.0
#define        ADC_P11                0x02        //IO引脚 Px.1
#define        ADC_P12                0x04        //IO引脚 Px.2
#define        ADC_P13                0x08        //IO引脚 Px.3
#define        ADC_P14                0x10        //IO引脚 Px.4
#define        ADC_P15                0x20        //IO引脚 Px.5
#define        ADC_P16                0x40        //IO引脚 Px.6
#define        ADC_P17                0x80        //IO引脚 Px.7
#define        ADC_P1_All        0xFF        //IO所有引脚

#define ADC_90T                (3<<5)
#define ADC_180T        (2<<5)
#define ADC_360T        (1<<5)
#define ADC_540T        0

#define ADC_POWER        0x80        //ADC电源控制位
//#define SPEED1        0x40        //ADC速度控制位
//#define SPEED0        0x20        //ADC速度控制位
#define ADC_FLAG        0x10        //模数转换结束标志,软件清0
#define ADC_START        0x08        //自动清0
//#define CHS2                0x04        //通道控制位
//#define CHS1                0x02        //通道控制位
//#define CHS0                0x01        //通道控制位

#define ADC_CH0                0
#define ADC_CH1                1
#define ADC_CH2                2
#define ADC_CH3                3
#define ADC_CH4                4
#define ADC_CH5                5
#define ADC_CH6                6
#define ADC_CH7                7

#define ADC_RES_H2L8        1
#define ADC_RES_H8L2        0

typedef struct
{
        u8        ADC_Px;                        //设置要做ADC的IO,        ADC_P10 ~ ADC_P17,ADC_P1_All
        u8        ADC_Speed;                //ADC速度                        ADC_90T,ADC_180T,ADC_360T,ADC_540T
        u8        ADC_Power;                //ADC功率允许/关闭        ENABLE,DISABLE
        u8        ADC_AdjResult;        //ADC结果调整,        ADC_RES_H2L8,ADC_RES_H8L2
        u8        ADC_Polity;                //优先级设置        PolityHigh,PolityLow
        u8        ADC_Interrupt;        //中断允许                ENABLE,DISABLE
} ADC_InitTypeDef;

ADC_EXT void        ADC_Inilize(ADC_InitTypeDef *ADCx);        //ADC初始化函数
ADC_EXT u8                ADC_Convert();                                                //启动ADC转换函数

#endif

#endif
注意:使用ADC函数库时,应先初始化ADC(ADC_Inilize(ADC_InitTypeDef *ADCx)),再循环调用顺序转换(ADC_Convert())。
若有疑问,可联系我。

评分

参与人数 2黑币 +58 收起 理由
杨雪飞 + 8 共享资料的黑币奖励!
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏6 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:691723 发表于 2020-2-10 21:01 | 只看该作者
我的程序是以中断方式查询ADC转换结果,极大简化程序复杂度,提高运行效率,同时并不影响其它程序功能模块的运行。
回复

使用道具 举报

板凳
ID:691723 发表于 2020-2-10 21:03 | 只看该作者
注意,使用本程序时,在ADC初始化前必须打开总中断。
回复

使用道具 举报

地板
ID:98880 发表于 2020-2-11 11:25 | 只看该作者
谢谢了,我回去测试一下。
回复

使用道具 举报

5#
ID:64765 发表于 2020-3-29 19:46 | 只看该作者
很好,学习了,谢谢分享。
回复

使用道具 举报

6#
ID:214276 发表于 2020-3-30 02:09 | 只看该作者
如果能配上12864显示屏或数码管做个数字电压表那就更好让人理解和应用了。
回复

使用道具 举报

7#
ID:27254 发表于 2020-3-30 08:22 | 只看该作者
谢谢发帖,使用自带AD往往数值不稳定,最好加上滤波就更完善了。
回复

使用道具 举报

8#
ID:65956 发表于 2020-3-30 08:32 | 只看该作者
现在看到这个贴,才发现原来也有人跟我写的基本一样,我也是作8路ADC采集,可根据需要指定哪一路进行采集,同调用1个函数去进行,节省程序空间
回复

使用道具 举报

9#
ID:215579 发表于 2020-3-31 09:21 | 只看该作者
想法非常好,哈哈
STC应该编写多一点函数库 反正现在单片机的FLASH也够用
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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