内容包含2019一些大赛题目,以及相关的了解。主要是F题电容的程序实现,采用F4系列单片机,有FDC2214的模块的原理图和PCB。分享给大家。
Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
单片机源程序如下:
- #include "delay.h"
- #include "sys.h"
- #include "usart.h"
- #include "myiic.h"
- #include "FDC2X2X_CMD.h"
- #include "FDC2214.h"
- #include "led.h"
- #include "key.h"
- #include "oled.h"
- #include "beep.h"
- #include "exti.h"
- #include "24cxx.h"
- #define ROUND_TO_UINT16(x) ((uint16_t)(x)+0.5)>(x)? ((uint16_t)(x)):((uint16_t)(x)+1) //将浮点数x四舍五入为uint16_t
- #define MAX_SIZE 100 //最大容量---纸张数
- #define GAP_MS 50 //校准测量采样时间间隔
- #define DATA_ACQUIRE_NUMBER 20 //数据采集数
- #define CH 1 //通道数
- #define duty_wideth 0.5 //滤波窗宽度调整系数
- u8 Flag_Work=0,Flag_Calibration=0; //Flag_Work :工作标志位。Flag_Work=0,设备处于待机状态;Flag_Work=1,设备处于测量状态。
- float Cap; //Cap :设备两极板间电容值,屏幕上实时显示
- int Paper_Number; //Paper_Number:设备最终计算得到的A4纸张数
- __align(4) u8 dtbuf[50]; //打印缓存器 __align(4)
- float Data_Raw[DATA_ACQUIRE_NUMBER],Data_Level[MAX_SIZE],data_acquire[DATA_ACQUIRE_NUMBER];
- //排序函数
- void bubble(float a[],int n)
- {
- int i,j;
- for(i=0; i<n-1; i++)
- {
- for(j=n-1; j>i; j--)
- {
- if(a[j]<a[j-1])
- {
- float t=a[j];
- a[j]=a[j-1];
- a[j-1]=t;
- }
- }
- }
- }
- //短路检测函数
- void Danger_Test()
- {
- if(Cap<0)
- {
- OLED_ShowString(0,0," Danger !!! ",16);
- BEEP=1;
- }
- }
- //启动测量函数
- void Start_Measure()
- {
- int i,j,k,index_min=0,counter,sum_effective;
- 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];
- if(Flag_Work==1) //如果KEY1按键按下,触发外部中断(工作标志位置1),进入此程序,程序进入测量状态
- {
- LED1=0; //LED1:测量指示灯
- for(i=0; i<DATA_ACQUIRE_NUMBER; i++)
- {
- Cap=FDC2214_read_CHx(CH); //Cap为设备所采的电容值
- data_acquire[i]=Cap;
- delay_ms(GAP_MS);
- }
- bubble(data_acquire,DATA_ACQUIRE_NUMBER);
- for(j=0; j<DATA_ACQUIRE_NUMBER; j++)
- {
- sum+=data_acquire[j];
- }
- baseline=sum/(float)DATA_ACQUIRE_NUMBER;
- div_min=(float)duty_wideth*(baseline-data_acquire[0]);
- div_max=(float)duty_wideth*(data_acquire[DATA_ACQUIRE_NUMBER-1]-baseline);
- high_limit=baseline+div_max;
- low_limit=baseline-div_min;
- counter=0;
- sum_effective=0.0f;
- for(k=0; k<DATA_ACQUIRE_NUMBER; k++)
- {
- Cap=FDC2214_read_CHx(CH);
- delay_ms(GAP_MS);
- if((Cap>low_limit)&&(Cap<high_limit))
- {
- data_measure_effective[counter]=Cap;
- sum_effective+=Cap;
- counter++;
- }
- }
- average_effective=sum_effective/(float)counter;
- for(i=0; i<MAX_SIZE; i++)
- {
- if(average_effective>Data_Level[i])
- break;
- }
- sum_div_sqr=0.0f;
- for(j=0; j<counter; j++)
- {
- div=data_measure_effective[j]-Data_Level[i-1];
- if(div<0)
- div=-div;
- else div=div;
- div_sqr=div*div;
- sum_div_sqr+=div_sqr;
- }
- variance_high=sum_div_sqr/(float)counter;
- for(j=0; j<counter; j++)
- {
- div=data_measure_effective[j]-Data_Level[i];
- if(div<0)
- div=-div;
- else div=div;
- div_sqr=div*div;
- sum_div_sqr+=div_sqr;
- }
- variance_low=sum_div_sqr/(float)counter;
- if(i>=1)
-
- {
- if(variance_high>variance_low)
- index_min=i;
- else
- index_min=i-1;
- }
- Paper_Number=index_min+1; //下标+1得到纸张数
- OLED_ShowNum(0,4,Paper_Number,10,16); //OLED显示纸张数
- BEEP=1;
- delay_ms(500);
- BEEP=0;
- LED1=1;
- Flag_Work=0; //将工作标志位置0,测试仪进入待机状态
- }
- }
- //校准函数
- void Calibration()
- {
- int i,j,k,counter;
- float sum,sum_effective,baseline,high_limit,low_limit,div_min,div_max;
- Flag_Calibration=0; //校准标志位,KEY2按键置1,相当于确定
- OLED_ShowString(0,0," Calibration ",16);
- for(i=0; i<MAX_SIZE; i++) //循环校准不同数量纸的电容值
- {
- sprintf((char *)dtbuf,"Place %d paper.",i+1);
- OLED_ShowString(0,2,dtbuf,16);
- OLED_ShowString(0,6," Press KEY2 !!!",16);
- while(Flag_Calibration==0)
- {
- Cap=FDC2214_read_CHx(CH);
- sprintf((char *)dtbuf,"Cap:%4.4f pF",Cap);
- OLED_ShowString(0,4,dtbuf,16);
- }
- sum=0;
- for(j=0; j<DATA_ACQUIRE_NUMBER; j++) //采集DATA_ACQUIRE_NUMBER次数据并取平均值存入AT24C02
- {
- Cap=FDC2214_read_CHx(CH);
- Data_Raw[j]=Cap;
- delay_ms(GAP_MS);
- }
- bubble(Data_Raw,DATA_ACQUIRE_NUMBER);
- for(j=0; j<DATA_ACQUIRE_NUMBER; j++)
- {
- sum+=Data_Raw[j];
- }
- baseline=sum/(float)DATA_ACQUIRE_NUMBER;
- div_min=(float)duty_wideth*(baseline-Data_Raw[0]);
- div_max=(float)duty_wideth*(Data_Raw[DATA_ACQUIRE_NUMBER-1]-baseline);
- high_limit=baseline+div_max;
- low_limit=baseline-div_min;
- counter=0;
- sum_effective=0.0f;
- for(k=0; k<DATA_ACQUIRE_NUMBER; k++)
- {
- Cap=FDC2214_read_CHx(CH);
- delay_ms(GAP_MS);
- if((Cap>low_limit)&&(Cap<high_limit))
- {
- sum_effective+=Cap;
- counter++;
- }
- }
- Data_Level[i]=sum_effective/(float)counter;
-
- if(i==0)
- {
- storFloatData DATA_LEVEL= { Data_Level[i] }; //向AT24C02写入数据
- Storage_WriteFloatNum(4*i,DATA_LEVEL);
- BEEP=1;
- delay_ms(500);
- BEEP=0;
- }
-
- if(i>=1)
- {
- if(Data_Level[i]<Data_Level[i-1])
- {
- storFloatData DATA_LEVEL= { Data_Level[i] }; //向AT24C02写入数据
- Storage_WriteFloatNum(4*i,DATA_LEVEL);
- BEEP=1;
- delay_ms(500);
- BEEP=0;
- }
- else
- {
- i=i-1;
- BEEP=1;
- delay_ms(200);
- BEEP=0;
- delay_ms(200);
- BEEP=1;
- delay_ms(200);
- BEEP=0;
- }
- }
- Flag_Calibration=0;
- }
- OLED_Clear();
- OLED_ShowString(0,2,"Calibration OK!!",16);
- BEEP=1; //校验通过后蜂鸣器响2秒
- delay_ms(2000);
- BEEP=0;
- OLED_Clear();
- }
- //循环读取AT24C02数据函数
- void Read_AT24C02()
- {
- int i;
- for(i=0; i<MAX_SIZE; i++)
- {
- storFloatData DATA=Storage_ReadFloatNum(4*i);
- Data_Level[i]=DATA.value; //录入到Data_Level数组
- }
- }
- int main()
- {
- delay_init(168); //延时函数初始化
- uart_init(115200); //串口初始化为115200
- LED_Init();
- KEY_Init();
- BEEP_Init();
- OLED_Init();
- EXTIX_Init();
- AT24CXX_Init();
- FDC2214_Init();
- Read_AT24C02(); //上电复位后读取AT24C02中存储的纸张数的电容值均值(做比对参考电容值)
- OLED_Clear();
- while(1)
- {
- Cap=FDC2214_read_CHx(CH); //读取电容值
- //----------OLED第一行显示内容-------------//
- OLED_ShowString(0,0,"|Paper Counter|",16);
- //----------OLED第二行显示内容-------------//
- OLED_ShowString(0,2,"----------------",16);
- //----------OLED第三行显示内容-------------//实时电容值
- sprintf((char *)dtbuf,"Cap:%4.4f",Cap);
- OLED_ShowString(0,4,dtbuf,16);
- OLED_ShowString(112,4,"pF",16);
- //----------OLED第四行显示内容-------------//纸张数
- OLED_ShowString(0,6,"Number:",16);
- OLED_ShowNum(56,6,Paper_Number,9,16);
- if(Flag_Calibration==1) //如果KEY2键按下,触发中断进入校准状态,不能退出(可复位重新开始)
- {
- Calibration(); //校准函数
- Flag_Calibration=0;
- }
- LED0=0; //LED0:待机指示灯--待机状态常亮
- BEEP=0; //蜂鸣器,待机状态不响
- Danger_Test(); //短路检测
- Start_Measure(); //启动测量
- }
- }
复制代码
所有资料51hei提供下载:
FDC2214_PCB.zip
(5.44 MB, 下载次数: 99)
|