• 设为首页
  • 收藏本站
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    论坛调试中-请所有人不要下载资料,下载失败,浪费积分后果自负。
    查看: 1195|回复: 8

    [技术文章] 基于STM32F103ZET6芯片的采样+滤波程序源码

    [复制链接]

    19

    主题

    86

    回帖

    0

    积分

    二级逆天

    积分
    0

    终身成就奖

    发表于 2020-3-2 00:37:50 | 显示全部楼层 |阅读模式
    例程介绍        

        这个例子演示如何使用ADC以及如何对ADC采样值进行滤波处理。

        Systick中断服务程序每个1ms启动并采集一次ADC值(PC4口线,可调电阻),并且对最近的20个样本进行求平均值。

        平均值保存在全局变量g_usAdcValue中。主程序定时读取这个变量,并将值打印到串口1。


        实际测试数据:

        (1)程序在CPU内部Flash或者内部RAM执行时,样本个数取20个,则采样值非常稳定(1个字跳动)

        (2)程序在外部SRAM运行时,由于3.3V电源波动,因此采样值跳动较大。

            

        请用串口线将开发板的COM1口连接到PC机的串口(或者USB串口),然后打开超级终端软件(XP自带的或者SecureCRT

        软件),可以在PC软件界面看到例程的运行信息。

       

        程序具有如下功能:

            - 复位后打印例程基本信息

            - 主程序定时将ADC值打印到串口1

            - 调节开发板上的可调电阻,超级终端界面上会显示一个不断旋转的字符 + 实时的ADC平均值


        程序执行结果如下:

            *************************************************************

            * 例程名称   : ADC采样和滤波例程

            * 例程版本   : 2.0

            * 发布日期   : 2011-10-16

            * 固件库版本 : 3.5.0

            *************************************************************

            请调节开发板上的精密可调电阻,观察ADC采样值的变化

            / PC4口线ADC采样值 =  2149 , 电压 = 1731mV


        对于Keil MDK,为了避免中文字符串告警,需要在C/C++编译选项中增加 --diag_suppress=870 参数。   


    单片机源程序如下:

    1. /*
    2. *********************************************************************************************************
    3. *                                          
    4. *        模块名称 : 主程序模块。
    5. *        文件名称 : main.c
    6. *        版    本 : V2.0
    7. *        说    明 : ADC采样和滤波例程。
    8. *        修改记录 :
    9. *                版本号  日期       作者    说明
    10. *                v1.0    2011-08-27 armfly  ST固件库V3.5.0版本。
    11. *                v2.0    2011-10-16 armfly  优化工程结构。
    12. *
    13. *********************************************************************************************************
    14. */
    15. #include "stm32f10x.h"                /* 如果要用ST的固件库,必须包含这个文件 */
    16. #include <stdio.h>                        /* 因为用到了printf函数,所以必须包含这个文件 */
    17. #include "bsp_usart.h"                /* printf函数定向输出到串口,所以必须包含这个文件 */
    18. #include "bsp_led.h"                /* LED指示灯驱动模块 */
    19. #include "bsp_button.h"                /* 按键驱动模块 */
    20. #include "bsp_timer.h"                /* systick定时器模块 */
    21. /* 定义例程名和例程发布日期 */                                       
    22. #define EXAMPLE_NAME        "ADC采样和滤波例程"
    23. #define EXAMPLE_DATE        "2011-10-16"
    24. #define DEMO_VER                "2.0"
    25. #define SAMP_COUNT        20                /* 样本个数,表示200ms内的采样数据求平均值 */
    26. /*
    27.         实际测试数据:
    28.         (1)程序在CPU内部Flash或者内部RAM执行时,样本个数取20个,则采样值非常稳定
    29.         (2)程序在外部SRAM运行时,由于3.3V电源波动,因此采样值跳动较大。
    30. */
    31. /* 仅允许本文件内调用的函数声明 */
    32. static void InitBoard(void);
    33. static void PrintfLogo(void);
    34. static uint16_t GetADC(void);
    35. static void ADC_Configuration(void);
    36. uint16_t g_usAdcValue;        /* ADC 采样值的平均值 */
    37. /*
    38. *********************************************************************************************************
    39. *        函 数 名: main
    40. *        功能说明: c程序入口
    41. *        形    参:无
    42. *        返 回 值: 错误代码(无需处理)
    43. *********************************************************************************************************
    44. */
    45. int main(void)
    46. {
    47.         uint16_t usValue;
    48.         /*
    49.                 由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
    50.                 启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
    51.                
    52.                 系统时钟缺省配置为72MHz,如果需要更改,可以修改:
    53.                 \Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\system_stm32f10x.c
    54.                 中配置系统时钟的宏。
    55.         */
    56.       
    57.         InitBoard();        /* 为了是main函数看起来更简洁些,我们将硬件初始化的代码封装到这个函数 */
    58.         PrintfLogo();        /* 打印例程Logo到串口1 */      
    59.         printf("请调节开发板上的精密可调电阻,观察ADC采样值的变化\r\n");
    60.         ADC_Configuration();        /* 配置PC4 为ADC1_IN14 */
    61.         bsp_StartTimer(1, 300);        /* 定时器0周期 200毫秒 */
    62.         /* 进入主程序循环体 */
    63.         while (1)
    64.         {
    65.                 CPU_IDLE();          /* 这个宏在bsp_timer.h 中定义,目前定义为空。用户可以修改这个宏实现CPU休眠和喂狗 */
    66.                 if (bsp_CheckTimer(1))        /* 定时到 */
    67.                 {
    68.                         bsp_StartTimer(1, 300);        /* 启动下个定时周期 */
    69.                         usValue = GetADC();
    70.                         /* 注意: 末尾只有 \r回车, 没有\n换行,可以使PC超级终端界面稳定在1行显示 */
    71.                         {
    72.                                 /* 超级终端界面上会显示一个不断旋转的字符
    73.                                 增加这个功能,是为了避免程序死机的假象,因为ADC采样值很稳定
    74.                                 */
    75.                                 static uint8_t pos = 0;
    76.                                 if (pos == 0)
    77.                                         printf("|");
    78.                                 else if (pos == 1)
    79.                                         printf("/");
    80.                                 else if (pos == 2)
    81.                                         printf("-");
    82.                                 else if (pos == 3)
    83.                                         printf("\\");                /* 注意:这个特殊字符需要转义 */
    84.                                 if (++pos >= 4)
    85.                                 {
    86.                                         pos = 0;
    87.                                 }
    88.                                 printf(" PC4口线ADC采样值 = %5d , 电压 = %4dmV\r",
    89.                                         usValue, ((uint32_t)usValue * 3300) / 4095);
    90.                         }
    91.                 }
    92.                 /* 这个地方可以插入 GetKey(), 扩充对按键的响应代码 */
    93.         }
    94. }
    95. /*
    96. *********************************************************************************************************
    97. *        函 数 名: ADC_Configuration
    98. *        功能说明: 配置ADC, PC4模式
    99. *        形    参:无
    100. *        返 回 值: 无
    101. *********************************************************************************************************
    102. */
    103. static void ADC_Configuration(void)
    104. {
    105.         GPIO_InitTypeDef GPIO_InitStructure;
    106.         ADC_InitTypeDef ADC_InitStructure;
    107.         __IO uint16_t ADCConvertedValue;
    108.     /* 使能 ADC1 and GPIOC clock */
    109.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
    110.         /* 配置PC4为模拟输入(ADC Channel14) */
    111.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    112.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    113.         GPIO_Init(GPIOC, &GPIO_InitStructure);
    114.         /* 配置ADC1, 不用DMA, 用软件触发 */
    115.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    116.         ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    117.         ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    118.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    119.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    120.         ADC_InitStructure.ADC_NbrOfChannel = 1;
    121.         ADC_Init(ADC1, &ADC_InitStructure);
    122.         /* 配置ADC1 规则通道14 channel14 configuration */
    123.         ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_55Cycles5);
    124.         /* 使能ADC1 DMA功能 */
    125.         ADC_DMACmd(ADC1, ENABLE);
    126.         /* 使能 ADC1 */
    127.         ADC_Cmd(ADC1, ENABLE);
    128.         /* 使能ADC1 复位校准寄存器 */
    129.         ADC_ResetCalibration(ADC1);
    130.         /* 检查ADC1的复位寄存器 */
    131.         while(ADC_GetResetCalibrationStatus(ADC1));
    132.         /* 启动ADC1校准 */
    133.         ADC_StartCalibration(ADC1);
    134.         /* 检查校准是否结束 */
    135.         while(ADC_GetCalibrationStatus(ADC1));
    136.         /* 软件启动ADC转换 */
    137.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    138. }
    139. /*
    140. *********************************************************************************************************
    141. *        函 数 名: AdcPro
    142. *        功能说明: ADC采样处理,插入1ms systick中断进行调用
    143. *        形    参:无
    144. *        返 回 值: 无
    145. *********************************************************************************************************
    146. */
    147. void AdcPro(void)
    148. {
    149.         static uint16_t buf[SAMP_COUNT];
    150.         static uint8_t write;
    151.         uint32_t sum;
    152.         uint8_t i;
    153.         buf[write] = ADC_GetConversionValue(ADC1);
    154.         if (++write >= SAMP_COUNT)
    155.         {
    156.                 write = 0;
    157.         }
    158.         /* 下面这段代码采用求平均值的方法进行滤波
    159.                 也可以改善下,选择去掉最大和最下2个值,使数据更加精确
    160.         */
    161.         sum = 0;
    162.         for (i = 0; i < SAMP_COUNT; i++)
    163.         {
    164.                 sum += buf[i];
    165.         }
    166.         g_usAdcValue = sum / SAMP_COUNT;        /* ADC采样值由若干次采样值平均 */
    167.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);        /* 软件启动下次ADC转换 */
    168. }
    169. /*
    170. *********************************************************************************************************
    171. *        函 数 名: GetADC
    172. *        功能说明: 读取ADC采样的平均值
    173. *        形    参:无
    174. *        返 回 值: 无
    175. *********************************************************************************************************
    176. */
    177. static uint16_t GetADC(void)
    178. {
    179.         uint16_t ret;
    180.         /* 因为        g_AdcValue 变量在systick中断中改写,为了避免主程序读变量时被中断程序打乱导致数据错误,因此需要
    181.         关闭中断进行保护 */
    182.         /* 进行临界区保护,关闭中断 */
    183.         __set_PRIMASK(1);  /* 关中断 */
    184.         ret = g_usAdcValue;
    185.         __set_PRIMASK(0);  /* 开中断 */
    186.         return ret;
    187. }
    188. /*
    189. *********************************************************************************************************
    190. *        函 数 名: InitBoard
    191. *        功能说明: 初始化硬件设备
    192. *        形    参:无
    193. *        返 回 值: 无
    194. *********************************************************************************************************
    195. */
    196. static void InitBoard(void)
    197. {      
    198.         /* 配置串口,用于printf输出 */
    199.         bsp_InitUart();
    200.       
    201.         /* 配置LED指示灯GPIO */
    202.         bsp_InitLed();
    203.         /* 配置按键GPIO, 必须在bsp_InitTimer之前调用 */
    204.         bsp_InitButton();
    205.         /* 初始化systick定时器,并启动定时中断 */
    206.         bsp_InitTimer();
    207. }
    208. /*
    209. *********************************************************************************************************
    210. *        函 数 名: PrintfLogo
    211. *        功能说明: 打印例程名称和例程发布日期, 接上串口线后,打开PC机的超级终端软件可以观察结果
    212. *        形    参:无
    213. *        返 回 值: 无
    214. *********************************************************************************************************
    215. */
    216. static void PrintfLogo(void)
    217. {
    218.         printf("*************************************************************\n\r");
    219.         printf("* 例程名称   : %s\r\n", EXAMPLE_NAME);        /* 打印例程名称 */
    220.         printf("* 例程版本   : %s\r\n", DEMO_VER);                /* 打印例程版本 */
    221.         printf("* 发布日期   : %s\r\n", EXAMPLE_DATE);        /* 打印例程日期 */
    222.         /* 打印ST固件库版本,这3个定义宏在stm32f10x.h文件中 */
    223.         printf("* 固件库版本 : %d.%d.%d\r\n", __STM32F10X_STDPERIPH_VERSION_MAIN,
    224.                         __STM32F10X_STDPERIPH_VERSION_SUB1,__STM32F10X_STDPERIPH_VERSION_SUB2);               
    225.         printf("* \n\r");        /* 打印一行空格 */
    226.         printf("* QQ    : 1295744630 \r\n");
    227.         printf("* Email : armfly@qq.com \r\n");
    228.         printf("* Copyright www.armfly.com 安富莱电子\r\n");
    229.         printf("*************************************************************\n\r");
    230. }
    复制代码
    ADC采样和滤波例程.rar (473 KB, 下载次数: 6)
    回复

    使用道具 举报

    38

    主题

    5068

    回帖

    2697

    积分

    二级逆天

    积分
    2697

    终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

    发表于 2020-3-2 09:00:20 | 显示全部楼层
    回复

    使用道具 举报

    0

    主题

    1万

    回帖

    7618

    积分

    二级逆天

    积分
    7618

    终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

    QQ
    发表于 2020-3-2 15:39:30 | 显示全部楼层
    回复

    使用道具 举报

    0

    主题

    1万

    回帖

    7618

    积分

    二级逆天

    积分
    7618

    终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

    QQ
    发表于 2020-3-2 15:40:03 | 显示全部楼层
    回复

    使用道具 举报

    196

    主题

    3558

    回帖

    0

    积分

    二级逆天

    积分
    0

    终身成就奖特殊贡献奖原创先锋奖

    发表于 2021-4-3 23:33:00 | 显示全部楼层
    回复

    使用道具 举报

    196

    主题

    3558

    回帖

    0

    积分

    二级逆天

    积分
    0

    终身成就奖特殊贡献奖原创先锋奖

    发表于 2021-4-3 23:33:11 | 显示全部楼层
    回复

    使用道具 举报

    196

    主题

    3558

    回帖

    0

    积分

    二级逆天

    积分
    0

    终身成就奖特殊贡献奖原创先锋奖

    发表于 2021-4-3 23:33:22 | 显示全部楼层
    回复

    使用道具 举报

    29

    主题

    1427

    回帖

    0

    积分

    二级逆天

    积分
    0

    终身成就奖特殊贡献奖原创先锋奖

    发表于 2023-2-7 08:32:33 | 显示全部楼层
    回复

    使用道具 举报

    0

    主题

    1458

    回帖

    3244

    积分

    二级逆天

    积分
    3244

    社区居民终身成就奖特殊贡献奖原创先锋奖

    QQ
    发表于 2023-2-7 08:33:53 | 显示全部楼层
    回复

    使用道具 举报

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

    本版积分规则

    公告:服务器刚移机,
    大家请不要下载东西。
    会下载失败


    QQ 手机版 小黑屋 监管台 遇到问题请联系QQ1308068381 逆天PCB论坛

    Powered by Discuz! X3.5 © 2001-2023

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