找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4862|回复: 3
收起左侧

FDC2214纸张计数显示装置原理图STM32源程序 2019电子设计大赛F题

[复制链接]
ID:273434 发表于 2020-10-18 20:32 | 显示全部楼层 |阅读模式
内容包含2019一些大赛题目,以及相关的了解。主要是F题电容的程序实现,采用F4系列单片机,有FDC2214的模块的原理图和PCB。分享给大家。

Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
51hei.png 51hei.png 51hei.png

单片机源程序如下:
  1. #include "delay.h"
  2. #include "sys.h"
  3. #include "usart.h"
  4. #include "myiic.h"
  5. #include "FDC2X2X_CMD.h"
  6. #include "FDC2214.h"

  7. #include "led.h"
  8. #include "key.h"
  9. #include "oled.h"
  10. #include "beep.h"
  11. #include "exti.h"
  12. #include "24cxx.h"

  13. #define ROUND_TO_UINT16(x)   ((uint16_t)(x)+0.5)>(x)? ((uint16_t)(x)):((uint16_t)(x)+1) //将浮点数x四舍五入为uint16_t
  14. #define MAX_SIZE   100                                //最大容量---纸张数
  15. #define GAP_MS   50                                        //校准测量采样时间间隔
  16. #define DATA_ACQUIRE_NUMBER 20                //数据采集数
  17. #define CH 1                                                //通道数
  18. #define duty_wideth        0.5                                //滤波窗宽度调整系数


  19. u8 Flag_Work=0,Flag_Calibration=0;                        //Flag_Work   :工作标志位。Flag_Work=0,设备处于待机状态;Flag_Work=1,设备处于测量状态。
  20. float Cap;                                                                        //Cap         :设备两极板间电容值,屏幕上实时显示
  21. int Paper_Number;                                                        //Paper_Number:设备最终计算得到的A4纸张数
  22. __align(4) u8 dtbuf[50];                                           //打印缓存器  __align(4)

  23. float Data_Raw[DATA_ACQUIRE_NUMBER],Data_Level[MAX_SIZE],data_acquire[DATA_ACQUIRE_NUMBER];

  24. //排序函数
  25. void bubble(float a[],int n)
  26. {
  27.     int i,j;
  28.     for(i=0; i<n-1; i++)
  29.     {
  30.         for(j=n-1; j>i; j--)
  31.         {
  32.             if(a[j]<a[j-1])
  33.             {
  34.                 float t=a[j];
  35.                 a[j]=a[j-1];
  36.                 a[j-1]=t;
  37.             }
  38.         }
  39.     }
  40. }

  41. //短路检测函数
  42. void Danger_Test()
  43. {
  44.     if(Cap<0)
  45.     {
  46.         OLED_ShowString(0,0,"   Danger !!!   ",16);

  47.         BEEP=1;
  48.     }
  49. }


  50. //启动测量函数
  51. void Start_Measure()
  52. {
  53.     int i,j,k,index_min=0,counter,sum_effective;
  54.     float variance_high,variance_low,sum_div_sqr,div,div_sqr,sum,baseline,div_min,div_max,high_limit,low_limit,average_effective,data_measure_effective[MAX_SIZE];
  55.     if(Flag_Work==1)        //如果KEY1按键按下,触发外部中断(工作标志位置1),进入此程序,程序进入测量状态
  56.     {
  57.         LED1=0;                                //LED1:测量指示灯

  58.         for(i=0; i<DATA_ACQUIRE_NUMBER; i++)
  59.         {
  60.             Cap=FDC2214_read_CHx(CH);                //Cap为设备所采的电容值
  61.             data_acquire[i]=Cap;
  62.             delay_ms(GAP_MS);
  63.         }


  64.         bubble(data_acquire,DATA_ACQUIRE_NUMBER);

  65.         for(j=0; j<DATA_ACQUIRE_NUMBER; j++)
  66.         {
  67.             sum+=data_acquire[j];
  68.         }
  69.         baseline=sum/(float)DATA_ACQUIRE_NUMBER;

  70.         div_min=(float)duty_wideth*(baseline-data_acquire[0]);
  71.         div_max=(float)duty_wideth*(data_acquire[DATA_ACQUIRE_NUMBER-1]-baseline);

  72.         high_limit=baseline+div_max;
  73.         low_limit=baseline-div_min;

  74.         counter=0;
  75.         sum_effective=0.0f;


  76.         for(k=0; k<DATA_ACQUIRE_NUMBER; k++)
  77.         {
  78.             Cap=FDC2214_read_CHx(CH);
  79.             delay_ms(GAP_MS);
  80.             if((Cap>low_limit)&&(Cap<high_limit))
  81.             {
  82.                 data_measure_effective[counter]=Cap;
  83.                 sum_effective+=Cap;
  84.                 counter++;
  85.             }
  86.         }

  87.         average_effective=sum_effective/(float)counter;

  88.         for(i=0; i<MAX_SIZE; i++)
  89.         {
  90.             if(average_effective>Data_Level[i])
  91.                 break;
  92.         }



  93.         sum_div_sqr=0.0f;
  94.         for(j=0; j<counter; j++)
  95.         {
  96.             div=data_measure_effective[j]-Data_Level[i-1];
  97.             if(div<0)
  98.                 div=-div;
  99.             else div=div;
  100.             div_sqr=div*div;
  101.             sum_div_sqr+=div_sqr;
  102.         }
  103.         variance_high=sum_div_sqr/(float)counter;


  104.         for(j=0; j<counter; j++)
  105.         {
  106.             div=data_measure_effective[j]-Data_Level[i];
  107.             if(div<0)
  108.                 div=-div;
  109.             else div=div;
  110.             div_sqr=div*div;
  111.             sum_div_sqr+=div_sqr;
  112.         }
  113.         variance_low=sum_div_sqr/(float)counter;


  114.                 if(i>=1)
  115.                        
  116.         {
  117.                         if(variance_high>variance_low)
  118.                                 index_min=i;
  119.                         else
  120.                                 index_min=i-1;
  121.                 }


  122.         Paper_Number=index_min+1;                        //下标+1得到纸张数



  123.         OLED_ShowNum(0,4,Paper_Number,10,16);        //OLED显示纸张数

  124.         BEEP=1;
  125.         delay_ms(500);
  126.         BEEP=0;
  127.         LED1=1;
  128.         Flag_Work=0;      //将工作标志位置0,测试仪进入待机状态
  129.     }
  130. }



  131. //校准函数
  132. void Calibration()
  133. {
  134.     int i,j,k,counter;
  135.     float sum,sum_effective,baseline,high_limit,low_limit,div_min,div_max;

  136.     Flag_Calibration=0;                //校准标志位,KEY2按键置1,相当于确定
  137.     OLED_ShowString(0,0,"   Calibration  ",16);

  138.     for(i=0; i<MAX_SIZE; i++)                //循环校准不同数量纸的电容值
  139.     {
  140.         sprintf((char *)dtbuf,"Place %d paper.",i+1);
  141.         OLED_ShowString(0,2,dtbuf,16);
  142.         OLED_ShowString(0,6,"  Press KEY2 !!!",16);
  143.         while(Flag_Calibration==0)
  144.         {
  145.             Cap=FDC2214_read_CHx(CH);
  146.             sprintf((char *)dtbuf,"Cap:%4.4f  pF",Cap);
  147.             OLED_ShowString(0,4,dtbuf,16);
  148.         }
  149.         sum=0;



  150.         for(j=0; j<DATA_ACQUIRE_NUMBER; j++)                                                //采集DATA_ACQUIRE_NUMBER次数据并取平均值存入AT24C02
  151.         {
  152.             Cap=FDC2214_read_CHx(CH);
  153.             Data_Raw[j]=Cap;
  154.             delay_ms(GAP_MS);
  155.         }

  156.         bubble(Data_Raw,DATA_ACQUIRE_NUMBER);

  157.         for(j=0; j<DATA_ACQUIRE_NUMBER; j++)
  158.         {
  159.             sum+=Data_Raw[j];
  160.         }
  161.         baseline=sum/(float)DATA_ACQUIRE_NUMBER;

  162.         div_min=(float)duty_wideth*(baseline-Data_Raw[0]);
  163.         div_max=(float)duty_wideth*(Data_Raw[DATA_ACQUIRE_NUMBER-1]-baseline);

  164.         high_limit=baseline+div_max;
  165.         low_limit=baseline-div_min;

  166.         counter=0;
  167.         sum_effective=0.0f;


  168.         for(k=0; k<DATA_ACQUIRE_NUMBER; k++)
  169.         {
  170.             Cap=FDC2214_read_CHx(CH);
  171.             delay_ms(GAP_MS);
  172.             if((Cap>low_limit)&&(Cap<high_limit))
  173.             {
  174.                 sum_effective+=Cap;
  175.                 counter++;
  176.             }
  177.         }

  178.         Data_Level[i]=sum_effective/(float)counter;
  179.                
  180.                 if(i==0)
  181.                 {
  182.                         storFloatData DATA_LEVEL= { Data_Level[i] };          //向AT24C02写入数据
  183.                         Storage_WriteFloatNum(4*i,DATA_LEVEL);
  184.                         BEEP=1;
  185.                         delay_ms(500);
  186.                         BEEP=0;
  187.                 }
  188.                
  189.         if(i>=1)
  190.         {
  191.             if(Data_Level[i]<Data_Level[i-1])
  192.             {
  193.                 storFloatData DATA_LEVEL= { Data_Level[i] };          //向AT24C02写入数据
  194.                 Storage_WriteFloatNum(4*i,DATA_LEVEL);
  195.                 BEEP=1;
  196.                 delay_ms(500);
  197.                 BEEP=0;
  198.             }
  199.             else
  200.             {
  201.                 i=i-1;
  202.                 BEEP=1;
  203.                 delay_ms(200);
  204.                 BEEP=0;
  205.                 delay_ms(200);
  206.                 BEEP=1;
  207.                 delay_ms(200);
  208.                 BEEP=0;
  209.             }
  210.         }
  211.         Flag_Calibration=0;
  212.     }
  213.     OLED_Clear();
  214.     OLED_ShowString(0,2,"Calibration OK!!",16);
  215.     BEEP=1;                                                                                //校验通过后蜂鸣器响2秒
  216.     delay_ms(2000);
  217.     BEEP=0;
  218.     OLED_Clear();
  219. }

  220. //循环读取AT24C02数据函数
  221. void Read_AT24C02()
  222. {
  223.     int i;
  224.     for(i=0; i<MAX_SIZE; i++)
  225.     {
  226.         storFloatData DATA=Storage_ReadFloatNum(4*i);
  227.         Data_Level[i]=DATA.value;                                                        //录入到Data_Level数组
  228.     }
  229. }

  230. int main()
  231. {
  232.     delay_init(168);            //延时函数初始化
  233.     uart_init(115200);                 //串口初始化为115200

  234.     LED_Init();
  235.     KEY_Init();
  236.     BEEP_Init();
  237.     OLED_Init();
  238.     EXTIX_Init();
  239.     AT24CXX_Init();
  240.     FDC2214_Init();

  241.     Read_AT24C02();                        //上电复位后读取AT24C02中存储的纸张数的电容值均值(做比对参考电容值)
  242.     OLED_Clear();
  243.     while(1)
  244.     {
  245.         Cap=FDC2214_read_CHx(CH);             //读取电容值

  246.         //----------OLED第一行显示内容-------------//
  247.         OLED_ShowString(0,0,"|Paper  Counter|",16);
  248.         //----------OLED第二行显示内容-------------//
  249.         OLED_ShowString(0,2,"----------------",16);
  250.         //----------OLED第三行显示内容-------------//实时电容值
  251.         sprintf((char *)dtbuf,"Cap:%4.4f",Cap);
  252.         OLED_ShowString(0,4,dtbuf,16);
  253.         OLED_ShowString(112,4,"pF",16);
  254.         //----------OLED第四行显示内容-------------//纸张数
  255.         OLED_ShowString(0,6,"Number:",16);
  256.         OLED_ShowNum(56,6,Paper_Number,9,16);
  257.         if(Flag_Calibration==1)                //如果KEY2键按下,触发中断进入校准状态,不能退出(可复位重新开始)
  258.         {
  259.             Calibration();                        //校准函数
  260.             Flag_Calibration=0;
  261.         }
  262.         LED0=0;                                //LED0:待机指示灯--待机状态常亮
  263.         BEEP=0;                                //蜂鸣器,待机状态不响
  264.         Danger_Test();                //短路检测
  265.         Start_Measure();        //启动测量
  266.     }
  267. }
复制代码

所有资料51hei提供下载:
FDC2214_PCB.zip (5.44 MB, 下载次数: 99)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:786920 发表于 2020-12-3 17:50 | 显示全部楼层
有实物展示吗
回复

使用道具 举报

ID:901785 发表于 2021-4-21 08:05 | 显示全部楼层
编译出来有两个错误呀
回复

使用道具 举报

ID:497515 发表于 2021-7-17 10:04 | 显示全部楼层
不能用,后面读的通道地址返回的数据都是0
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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