重在分享和整理:这个题目算是入门stm32之后第一次走出开发板,用最小系统做的一个电赛题目,收获很多,希望看到的朋友们在大学期间能够多参加机甲大师,电赛等一些含金量比较高的比赛,还可以考一下软考(嵌入式系统设计师),刚开始大一,大二上学期玩开发板期间可以参加蓝桥杯这样的比赛 以赛促学真的很不错
提示:以下是本篇文章正文内容,下面案例可供参考
前期工作:硬件:了解NE555搭建出较好,研究外部电路,搭建出较稳定的硬件结构。
软件:按键使用,屏幕或者串口的使用,学习PWM输入捕获,AT24C02的读写操作,滤波算法,查询算法,
思路:使用的STM32自带的输入捕获,让捕获频率在1Mhz(1um)级别,捕获精度可以说足够了。一个按键控制校准分别捕获1张2张3张…等纸张的频率存储到AT24C02上,最好每捕获一张在屏幕给一个提示值,方便观察。另一个按键主要是查表,如果这次捕获的频率跟AT24C02表格中的值一样,把它通过算法进行输出。大致思路就是这样。
难点:硬件上的不稳定
整体硬件展示(如下图)
现成:stm32f407 mcu 4.3触摸屏 FDC2214(有钱省事可以直接使用,不用搭建ne555)
搭建:使用NE555芯片、覆铜板、电阻、电容等搭建成一个电容测量电路(电容的不同会引起OUT引脚输出频率的变化,mcu测主要工作就是测量ne555 out管脚输出的频率大小。硬件搭建较为简单,难点在软件实现上)
搭建NE555外部电路:实则只需要两个电阻、两个电容和两个覆铜板
硬件搭建难点:要给两覆铜板设计一个结构,1.使得每次覆铜板重合的部分完全相同,2.使得不管是几张纸受到的压力都是相同的不能是纸张变多了,空间给的是个定值,纸张的受到的压力就是越来越大。连接覆铜板上的两个引线最好使用双绞线,管脚线的话每次移动都能使频率发生变化。遵循这几个原则设计结构比较合理。
广告,哈哈:NE555物美价廉,适合学习阶段使用,提高自己的动手能力
***********************************列出部分代码#######################
代码如下(示例):
int main(void)
{
//*********************中断优先级NVIC配置**************************
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
//*************************驱动初始化************************
delay_init(168); //初始化延时函数
uart_init(115200);//初始化串口波特率为115200
LCD_Init();
Led_Init();
AT24CXX_Init();
EXTIX_Init();
TIM14_PWM_Init(1000-1,84-1); //84M/84=1Mhz的计数频率计数到1000,PWM频率为1M/1000=1Khz
TIM3_CH1_Cap_Init(0XFFFFFFFF,84-1); //以1Mhz的频率计数 1um
//************************功能实现*************************
AT24CXX_WriteOneByte(0,0);
AT24CXX_WriteOneByte(1,0);//开始两个存储单元保存没有纸张对应的频率
AT24CXX_Read(0,list,80);//测试用,读取eepram中的数值
Lcd_Config();
while(1)
{
TIM_SetCompare1(TIM14,600); //修改比较值,修改占空比 600/1000
//USART_Per();//串口建立关系表函数 调试阶段,用串口建立一个纸张——频率的表格,以防硬件电路影响代码
Capture();
EXTI_Status=Key_Scanf(0);
if(EXTI_Status==1)//wk_up按键 右键 校验
{
KK_UP_operation();
}
if(EXTI_Status==2)//key0按键 左键 检测
{
KEY0_operation();
}
}
}
其中:temp为为PWM捕获的值,见1.1输入捕获
代码如下(示例):
void KK_UP_operation(void)
{
u32 static number;
LCD_Clear(WHITE);
Lcd_Config();
EXTI_Status=0;
LED1=1;
LED2=0;
eeprom_add += 2;
xiaoyan(eeprom_add,temp);
//输出提示
sprintf((char*)successfulp_Buff,"Store Success:%dn",++number);
LCD_ShowString(30,230,210,24,24,successfulp_Buff);
printf("Store successful\r\n");
}
void Capture(void)
{
if(TIM3CH1_CAPTURE_STA&0X80)//成功捕获到了一次高电平
{
temp=TIM3CH1_CAPTURE_STA&0X3F;
temp*=0XFFFFFFFF; //溢出时间总和
temp+=TIM3CH1_CAPTURE_VAL; //得到总的高电平时间
sprintf((char*)PWM_In_Buff,"HIGH:%d Mhz",temp);
LCD_ShowString(30,260,230,24,24,PWM_In_Buff);
TIM3CH1_CAPTURE_STA=0; //开启下一次捕获
}
}
代码如下(示例):
void KEY0_operation(void)
{
LCD_Clear(WHITE);
Lcd_Config();
EXTI_Status=0;
LED1=0;
LED2=1;
Poper_Num = Detection(temp);
sprintf((char*)Paper_Buff,"PAPER_NUM:%dz",Poper_Num);
LCD_ShowString(30,290,210,24,24,Paper_Buff);
}
这篇文章只是展示了一个大概思路。对于捕获建议捕获一个周期,因为电容的变化会引起频率的变化,而一个周期才能在一定程度上反映出频率的大小变化,我只是捕获了一个周期的高电平时间,没有一般性,对于实际应用不适用,最好是捕获一个周期,或者几个周期求平均值。
但是之后相出一个好一点的办法,就是用定时器,设置为上升沿触发,记录触发的次数,能直观的反映出频率的大小,如果最求精确的话定时的周期是一个值得讨论的问题,并不是时间越久越好。