(4)在led.c文件中添加以下代码
(5)在tpad.c文件内添加以下代码
#include "tpad.h"
#include "delay.h"
/***************************************************
Name :TPAD_Get_Value
Function :触摸按键值获取
Paramater :None
Return :获取的充电时间
***************************************************/
u16 TPAD_Get_Value()
{
//电容放电
GPIOA->CRL &= 0xFFFFFF0F ; //PA1输入
GPIOA->CRL |= 0x00000030 ; //推挽输出
GPIOA->ODR &= ~( 1<<1 ) ; //输出低电平放电
delay_ms( 5 ) ;
TIM5->SR = 0 ; //清除标记
TIM5->CNT = 0 ; //归零
GPIOA->CRL &= 0xFFFFFF0F ; //PA1输入
GPIOA->CRL |= 0x00000040 ; //浮空输入
//等待捕获上升沿
while( ( TIM5->SR&0x04 )==0 )
{
if( TIM5->CNT>( 65535-500 ) )
return TIM5->CNT ;
}
return TIM5->CCMR2 ;
}
/***************************************************
Name :TPAD_Get_MaxVal
Function :触摸按键最大值获取
Paramater :None
Return :获取的最大充电时间
***************************************************/
u16 TPAD_Get_MaxVal( u8 n )
{
u16 temp=0;
u16 res=0;
while( n-- )
{
temp = TPAD_Get_Value() ;
if( temp>res )
res = temp ;
}
return res ;
}
/***************************************************
Name :TPAD_Init
Function :触摸按键初始化
Paramater :None
Return :None
***************************************************/
TPADData TPAD_Data ;
void TPAD_Init()
{
u16 buff[ 10 ], temp ;
u8 i, j ;
RCC->APB2ENR |= 1<<2 ;
GPIOA->CRL &= 0xFFFFFF0F ; //PA1 输入
GPIOA->CRL |= 0x00000040 ; //浮空输入
RCC->APB1ENR |= 1<<3 ; //TIM5时钟开启
TIM5->ARR = 65535 ;
TIM5->PSC = 5 ;
TIM5->CCMR1 |= 1<<8 ; //选择输入端IC2映射到TI2上
TIM5->CCMR1 &= ~( 1<<12 ) ; //采样频率8分频
TIM1->CCMR1 &= ~( 1<<10 ) ; //配置输入不分频
TIM5->CCER &= ~( 1<<5 ) ; //上升沿捕获
TIM5->CCER |= 1<<4 ; //允许捕获功能
TIM5->CR1 |= 1<<0 ; //开启定时器5
//连续采样10次
for( i=0; i<10; i++ )
{
buff[ i ] = TPAD_Get_Value() ;
delay_ms( 10 ) ;
}
//排序
for( i=0; i<9; i++ )
{
for( j=i+1; j<10; j++ )
{
//升序排列
if( buff[ i ]>buff[ j ] )
{
temp= buff[ i ] ;
buff[ i ] = buff[ j ] ;
buff[ j ] = temp ;
}
}
}
temp = 0 ;
//获取中间数据的均值
for( i=2; i<8; i++ )
temp += buff[ i ] ;
TPAD_Data.value = temp/6 ;
}
/***************************************************
Name :TPAD_Scan
Function :触摸按键扫描
Paramater :None
Return :None
***************************************************/
void TPAD_Scan()
{
u16 rval ;
rval = TPAD_Get_MaxVal( 3 ) ;
if( rval>( TPAD_Data.value+100 ) )
TPAD_Data.State = 1 ; //手指按下
}
(6)在1.c文件内添加主函数
#include "sys.h"
#include "delay.h"
#include "usart1.h"
#include "led.h"
#include "tpad.h"
int main()
{
STM32_Clock_Init( 9 ) ; //STM32时钟初始化
SysTick_Init( 72 ) ; //SysTick初始化
USART1_Init( 72, 115200 ) ; //初始化串口1波特率115200
LED_Init() ; //LED初始化
TPAD_Init() ; //触摸按键初始化
while( 1 )
{
TPAD_Scan() ; //触摸按键扫描
if( TPAD_Data.State==1 )
{
LED = 0 ;
TPAD_Data.State = 0 ;
}
else
LED = 1 ;
}
}
——————————————分割线——————————————
8.4 STM32工程管理
这里的总结是针对与之前所学的所有嵌入式内容进行总结,随着后续代码越来越多,对于工程的管理显得格外重要,不仅仅是采用本章节介绍的方法管理工程代码,对于后续的Linux开发和操作系统移植也最好是按照固定的工程格式进行管理。
对于STM32的工程可以划分为以下几个部分:
(1)过程文件以及最终生成的hex文件:这些文件通通放置在工程1级目录下的OBJECT文件中,文件中的内容如下图所示。
图中标注部分就是最终生成的hex文件,其他的文件均属于过程文件,集成开发系统IDE编译的实质其实就是采用gcc交叉编译器将我们编写的代码转换成对应的机器代码的过程,具体的步骤会在Linux系统移植中描述,这里只需要知道利用交叉编译器进行编译的时候会产生大量的链接文件和过程文件,这些文件统统放置在OBJECT目录下。将工程文件中的过程文件放置在该目录下的设置方式如下图所示。
(2)主函数文件及主工程文件:在Keil中创建的工程,以及包括main函数的c文件都位于这个目录内。
图中标注的3个文件都是必不可少的文件,带有Keil图标的文件就是工程文件,里面包含了整个工程所需的头文件,文件路径以及编译器位置,文本文件图标的则是c文件,main函数就放在这个位置,.s后缀的为汇编启动文件,用于帮助芯片创建C代码运行环境,初始化堆栈等功能,为了达到最快效率,所以采用汇编语言来编写这个文件。
(3)自定义系统文件:自定义的系统文件位于SYSTEM目录中,目录内有3个子目录,分别是sys,delay和usart1,如下图所示。
delay目录:是利用SysTick时钟来实现的延时功能,主要有毫秒级延时和微秒级延时;
usart1目录:则是利用串口1来实现printf打印输出的功能,主要用于调试数据的输出;
sys目录:是最基础的工程文件,这个目录内有1个c文件和2个h文件,c文件主要实现STM32时钟树的配置和中断系统的设置功能,是C函数中最重要的一个文件,stmxx.h文件则是最底层的寄存器定义文件,里面定义了STM32芯片内部所有寄存器的地址和结构,通过C语言来调用这里面的寄存器实现芯片的控制功能。
(4)驱动文件:驱动文件位于HEADERWARE目录中,用于存放项目所用到的驱动,比如之前实验所用到的LED,KEY,TIM这些外设都属于驱动文件内容。
至此整个工程的目录结构如下图所示。