搞了几天STM32F051的触摸按键功能,最后发现其实很简单。最开始下载了官方的库,结果使用的时候发现程序居然会跑飞,后来还是自己写吧,写完了才发现原来很简单,这里把代码贴出来和大家分享。
// --------------------TSCtrl.h---------------------------
#pragma once
enum TSCStatus
{
TSC_RELEASE,
TSC_PRESSED
};
class TSCtrl
{
public:
// 构造对象。
static TSCtrl &Construction(void)
{
static TSCtrl ts_obj;
return ts_obj;
}
// 扫描端口。
void Scan(void);
// 获取状态。
TSCStatus GetPortStatus(int index);
~TSCtrl();
private:
TSCtrl();
};
#define tsc (TSCtrl::Construction())
//-----------------------TSCtrl.cpp-----------------------------
#include "TSCtrl.h"
#include "stm32f0xx_gpio.h"
#include "stm32f0xx_rcc.h"
#include
#define THRESHOLD 30 // 按下时刻的门槛,根据实际情况修改此值。
#define PORT_NR 3
struct PortStatus
{
short fixed_value;
short current_value;
TSCStatus status;
unsigned short enable_mask;
};
struct ScanTrace
{
PortStatus port[PORT_NR];
char port_index;
};
ScanTrace _trace =
{
935, 0, TSC_RELEASE, 1 << 12, // 935根据你的板卡而定,它是指在没有触碰按钮时刻采集的数据,该值在IOGXCR寄存器中。
926, 0, TSC_RELEASE, 1 << 13, // 1<<13这些数据也要根据实际情况修改,这里使用的是GP4_IO1, GP4_IO2,GP4_IO4。
1100, 0, TSC_RELEASE, 1 << 15,
0
};
#define CAP_PORT GPIOA // 根据实际情况修改。
#define SAMPCAP_PIN GPIO_Pin_11
#define CHANNEL0_PIN GPIO_Pin_9
#define CHANNEL1_PIN GPIO_Pin_10
#define CHANNEL2_PIN GPIO_Pin_12
static void _init_hw(void)
{
// 打开时钟。
::RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_InitTypeDef gpio_config;
gpio_config.GPIO_Mode = GPIO_Mode_AF;
gpio_config.GPIO_OType = GPIO_OType_OD;
gpio_config.GPIO_Speed = GPIO_Speed_2MHz;
gpio_config.GPIO_PuPd = GPIO_PuPd_NOPULL;
gpio_config.GPIO_Pin = SAMPCAP_PIN;
::GPIO_Init(CAP_PORT, &gpio_config); // 初始化CAP引脚。
gpio_config.GPIO_OType = GPIO_OType_PP;
gpio_config.GPIO_Pin = CHANNEL0_PIN | CHANNEL1_PIN | CHANNEL2_PIN;
::GPIO_Init(CAP_PORT, &gpio_config); // 初始化CHANNEL引脚。
// 重定义引脚的功能。
::GPIO_PinAFConfig(CAP_PORT, 9, GPIO_AF_3);
::GPIO_PinAFConfig(CAP_PORT, 10, GPIO_AF_3);
::GPIO_PinAFConfig(CAP_PORT, 11, GPIO_AF_3);
::GPIO_PinAFConfig(CAP_PORT, 12, GPIO_AF_3);
::RCC_AHBPeriphClockCmd(RCC_AHBPeriph_TS, ENABLE);
// CTPH = 1x tPGCLK, CTPL = 1x tPGCLK, PGPSC = 5(fHCLK/32), MCV = 6, TSCE = ENABLE
TSC->CR = (0 << 28) | (0 << 24) | (5 << 12) | (6 << 5) | (1 << 0);
// 关闭施密特出发。
unsigned tmp_value = 0xFFFFFFFF;
tmp_value &= (unsigned)~((unsigned)1 << 12);
tmp_value &= (unsigned)~((unsigned)1 << 13);
tmp_value &= (unsigned)~((unsigned)1 << 14);
tmp_value &= (unsigned)~((unsigned)1 << 15);
TSC->IOHCR &= tmp_value;
// Sampling enabled
tmp_value = 0;
tmp_value |= (unsigned)((unsigned)1 << 14);
TSC->IOSCR |= tmp_value;
// Channel enabled, G4_IO4 G4_IO2 G4_IO1
// TSC->IOCCR = (0x01 << 12);
// Enable group, G4
TSC->IOGCSR |= (1 << 3);
}
static int _wait_eoc(void)
{
int ret = 0;
if (TSC->ISR & 0x01)
{
// Check MCEF flag
if (TSC->ISR & 0x02)
{
ret = 0;
}
else
{
ret = 1;
}
}
return ret;
}
static void _scan_channel(int index)
{
TSC->IOCCR = _trace.port[index].enable_mask;
TSC->ICR |= 0x03;
TSC->CR |= 0x02;
int delay_cnt = 0;
while(_wait_eoc() == 0)
{
if(++delay_cnt > 10000) // 避免死循环。
{
_trace.port[index].status = TSC_RELEASE;
return;
}
}
_trace.port[index].current_value = TSC->IOGXCR[3];
short diff = ::abs(_trace.port[index].current_value - _trace.port[index].fixed_value);
if(diff > THRESHOLD)
{
_trace.port[index].status = TSC_PRESSED;
}
else
{
_trace.port[index].status = TSC_RELEASE;
}
}
void TSCtrl::Scan(void)
{
_scan_channel(_trace.port_index++);
_trace.port_index = (_trace.port_index >= PORT_NR) ? 0 : _trace.port_index;
}
TSCStatus TSCtrl::GetPortStatus(int index)
{
return _trace.port[index].status;
}
TSCtrl::TSCtrl()
{
_init_hw();
}
TSCtrl::~TSCtrl()
{
}
使用代码如下:
int main(void)
{
TSCStatus t;
while(1)
{
tsc.Scan();
t = tsc.GetPortStatus(1);
t = tsc.GetPortStatus(2);
t = tsc.GetPortStatus(3);
}
}
上一篇:使用 STM32 测量频率和占空比的几种方法
下一篇:STM32 PCB触摸按键(RC检测法)
推荐阅读最新更新时间:2024-03-16 16:10