找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于STM32F103ZET6芯片的采样+滤波程序源码

[复制链接]
跳转到指定楼层
楼主
ID:170655 发表于 2018-9-17 11:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
可用作开发学习使用
/*
*********************************************************************************************************
*
*    例程名称      : Ex004-按键检测例程(软件滤波+FIFO)
*    例程版本      : V2.0
*    ST固件库版本  :V3.5.0
*    作    者      : armfly
*    发布日期      : 2011-10-16
*
*    开发环境      : KEIL的uVision V3.70、uVision V4.13、IAR的EWARM V5.30
*
*    修改记录      :
*        2010-09-27 发布V1.0版本,固件库为V3.1.2
*        2011-03-20 发布V1.1版本,固件库为V3.4.0
*        2011-11-16 发布2.0版本,固件库为V3.5.0,优化工程结构,打印信息改为中文
*
*********************************************************************************************************
*/

【1】例程介绍        
    这个例子演示如何使用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 参数。   

    本程序支持在CPU内部Flash、CPU内部RAM和CPU外部RAM调试。在CPU内部RAM和CPU外部SRAM调试时,无需切换开发板上的
    启动模式拨码开关。请将拨码开关拨到Flash位置。

单片机源程序如下:
  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. }
复制代码

所有资料51hei提供下载:
ADC采样和滤波例程.rar (472.09 KB, 下载次数: 112)



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

使用道具 举报

沙发
ID:485105 发表于 2019-6-5 09:39 | 只看该作者
666,用了
回复

使用道具 举报

板凳
ID:361429 发表于 2019-12-8 17:38 | 只看该作者
谢谢分享。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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