STMicro STMTouch Driver 使用 5 通道单电极设计解决线性传感器问题
STMicro STMTouch Driver Usage of a 5 channel Mono electrode design for Linear Sensor Problems
我正在使用一个定制板,它有 8 个通道,由三个触摸键和一个线性传感器组成。
有 8 个通道 IOs、三个采样 IOs 并且没有屏蔽配置。其中三个通道用于三个触摸键。其中五个通道用于线性传感器。
我使用过 STM3270B 探索板,它在 Half-Ended 电极设计 (LIN_H) 中设置了三个通道。我已经完成了该板提供的非中断实现示例。
我使用过 STM3207 评估板,它有两个通道设置为两个触摸键。
在我的定制板上,触摸键工作完美。五通道线性传感器不能完全工作。所有五个垫确实检测到触摸,但就数据位置而言,它失败了。该示例在单个通道中包含所有 ios。据我所知,没有一个示例使用 5 个通道,分为两个 TSC 组。 STMTouch Driver 用户手册中提到了它,但我将不得不再次查找代码示例。
问题在于确定传感器值的宏 LINEAR_POSITION = MyLinRots[0].p_Data->Position 有两个结果。如果与组 1 IOs 关联的两个打击垫中的任何一个被触摸,检测宏将正确触发,但 LINEAR_POSITION 值为 0x2。同样,如果与组 2 IOS 关联的三个打击垫被触摸,检测宏会正确触发,但 LINEAR_POSITION 值为 0xC。
我认为每个垫的值会在 0 到 255 之间变化,分为 5 种方式。我查看了原始位置而不是缩放后的位置,但它的行为类似。
这是我的频道、库、触摸键布局,linear/rotary 和 objects 分布在 header 文件和源文件中。
header:
/* Channel IOs definition */
// The three touchkey channels
#define CHANNEL_0_IO_MSK (TSC_GROUP6_IO2)
#define CHANNEL_0_GRP_MSK (TSC_GROUP6)
#define CHANNEL_0_SRC (TSC_GROUP6_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_0_DEST (0) /* Index in destination result array */
#define CHANNEL_1_IO_MSK (TSC_GROUP6_IO3)
#define CHANNEL_1_GRP_MSK (TSC_GROUP6)
#define CHANNEL_1_SRC (TSC_GROUP6_IDX)
#define CHANNEL_1_DEST (1)
#define CHANNEL_2_IO_MSK (TSC_GROUP6_IO4)
#define CHANNEL_2_GRP_MSK (TSC_GROUP6)
#define CHANNEL_2_SRC (TSC_GROUP6_IDX)
#define CHANNEL_2_DEST (2)
// The five linrot channels
#define CHANNEL_3_IO_MSK (TSC_GROUP1_IO3)
#define CHANNEL_3_GRP_MSK (TSC_GROUP1)
#define CHANNEL_3_SRC (TSC_GROUP1_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_3_DEST (3) /* Index in destination result array */
#define CHANNEL_4_IO_MSK (TSC_GROUP1_IO4)
#define CHANNEL_4_GRP_MSK (TSC_GROUP1)
#define CHANNEL_4_SRC (TSC_GROUP1_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_4_DEST (4) /* Index in destination result array */
#define CHANNEL_5_IO_MSK (TSC_GROUP2_IO2)
#define CHANNEL_5_GRP_MSK (TSC_GROUP2)
#define CHANNEL_5_SRC (TSC_GROUP2_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_5_DEST (5) /* Index in destination result array */
#define CHANNEL_6_IO_MSK (TSC_GROUP2_IO3)
#define CHANNEL_6_GRP_MSK (TSC_GROUP2)
#define CHANNEL_6_SRC (TSC_GROUP2_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_6_DEST (6) /* Index in destination result array */
#define CHANNEL_7_IO_MSK (TSC_GROUP2_IO4)
#define CHANNEL_7_GRP_MSK (TSC_GROUP2)
#define CHANNEL_7_SRC (TSC_GROUP2_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_7_DEST (7) /* Index in destination result array */
/* Shield IOs definition */
#define SHIELD_IO_MSK (0) // orig (TSC_GROUP7_IO3) we dont have a shield
/* Banks definition */
// The touch key bank
#define BANK_0_NBCHANNELS (1)
#define BANK_0_MSK_CHANNELS (CHANNEL_0_IO_MSK | SHIELD_IO_MSK)
#define BANK_0_MSK_GROUPS (CHANNEL_0_GRP_MSK)
#define BANK_1_NBCHANNELS (1)
#define BANK_1_MSK_CHANNELS (CHANNEL_1_IO_MSK | SHIELD_IO_MSK)
#define BANK_1_MSK_GROUPS (CHANNEL_1_GRP_MSK)
#define BANK_2_NBCHANNELS (1)
#define BANK_2_MSK_CHANNELS (CHANNEL_2_IO_MSK | SHIELD_IO_MSK)
#define BANK_2_MSK_GROUPS (CHANNEL_2_GRP_MSK)
// The linrot bank
#define BANK_3_NBCHANNELS (5)
#define BANK_3_MSK_CHANNELS (CHANNEL_3_IO_MSK | CHANNEL_4_IO_MSK | CHANNEL_5_IO_MSK | CHANNEL_6_IO_MSK| CHANNEL_7_IO_MSK | SHIELD_IO_MSK)
#define BANK_3_MSK_GROUPS (CHANNEL_3_GRP_MSK | CHANNEL_4_GRP_MSK | CHANNEL_5_GRP_MSK | CHANNEL_6_GRP_MSK | CHANNEL_7_GRP_MSK )
设置定义的源文件
/* define for the linear */
#define LINEAR_DETECT ((MyLinRots[0].p_Data->StateId == TSL_STATEID_DETECT) || \
(MyLinRots[0].p_Data->StateId == TSL_STATEID_DEB_RELEASE_DETECT))
#define LINEAR_POSITION (MyLinRots[0].p_Data->Position)
/*============================================================================*/
/* Channels */
/*============================================================================*/
/* Source and Configuration (ROM) */
CONST TSL_ChannelSrc_T MyChannels_Src[TSLPRM_TOTAL_CHANNELS] = {
// The three touchkey channels
{ CHANNEL_0_SRC, CHANNEL_0_IO_MSK, CHANNEL_0_GRP_MSK },
{ CHANNEL_1_SRC, CHANNEL_1_IO_MSK, CHANNEL_1_GRP_MSK },
{ CHANNEL_2_SRC, CHANNEL_2_IO_MSK, CHANNEL_2_GRP_MSK },
// The five linrot channels
{ CHANNEL_3_SRC, CHANNEL_3_IO_MSK, CHANNEL_3_GRP_MSK },
{ CHANNEL_4_SRC, CHANNEL_4_IO_MSK, CHANNEL_4_GRP_MSK },
{ CHANNEL_5_SRC, CHANNEL_5_IO_MSK, CHANNEL_5_GRP_MSK },
{ CHANNEL_6_SRC, CHANNEL_6_IO_MSK, CHANNEL_6_GRP_MSK },
{ CHANNEL_7_SRC, CHANNEL_7_IO_MSK, CHANNEL_7_GRP_MSK }
};
/* Destination (ROM) */
CONST TSL_ChannelDest_T MyChannels_Dest[TSLPRM_TOTAL_CHANNELS] = {
// The three touchkey channels
{ CHANNEL_0_DEST },
{ CHANNEL_1_DEST },
{ CHANNEL_2_DEST },
// The five linrot channels
{ CHANNEL_3_DEST },
{ CHANNEL_4_DEST },
{ CHANNEL_5_DEST },
{ CHANNEL_6_DEST },
{ CHANNEL_7_DEST },
};
/* Data (RAM) */
TSL_ChannelData_T MyChannels_Data[TSLPRM_TOTAL_CHANNELS];
/*============================================================================*/
/* Banks */
/*============================================================================*/
/* List (ROM) */
CONST TSL_Bank_T MyBanks[TSLPRM_TOTAL_BANKS] = {
// The three touchkey bankss
{&MyChannels_Src[0], &MyChannels_Dest[0], MyChannels_Data, BANK_0_NBCHANNELS, BANK_0_MSK_CHANNELS, BANK_0_MSK_GROUPS},
{&MyChannels_Src[1], &MyChannels_Dest[1], MyChannels_Data, BANK_1_NBCHANNELS, BANK_1_MSK_CHANNELS, BANK_1_MSK_GROUPS},
{&MyChannels_Src[2], &MyChannels_Dest[2], MyChannels_Data, BANK_2_NBCHANNELS, BANK_2_MSK_CHANNELS, BANK_2_MSK_GROUPS},
// The one linrot bank
{&MyChannels_Src[3], &MyChannels_Dest[3], MyChannels_Data, BANK_3_NBCHANNELS, BANK_3_MSK_CHANNELS, BANK_3_MSK_GROUPS}
};
/*============================================================================*/
/* Touchkey sensors */
/*============================================================================*/
/* Data (RAM) */
TSL_TouchKeyData_T MyTKeys_Data[TSLPRM_TOTAL_TKEYS];
/* Parameters (RAM) */
TSL_TouchKeyParam_T MyTKeys_Param[TSLPRM_TOTAL_TKEYS];
/* State Machine (ROM) */
void MyTKeys_ErrorStateProcess(void);
void MyTKeys_OffStateProcess(void);
CONST TSL_State_T MyTKeys_StateMachine[] = {
/* Calibration states */
/* 0 */ { TSL_STATEMASK_CALIB, TSL_tkey_CalibrationStateProcess },
/* 1 */ { TSL_STATEMASK_DEB_CALIB, TSL_tkey_DebCalibrationStateProcess },
/* Release states */
/* 2 */ { TSL_STATEMASK_RELEASE, TSL_tkey_ReleaseStateProcess },
#if TSLPRM_USE_PROX > 0
/* 3 */ { TSL_STATEMASK_DEB_RELEASE_PROX, TSL_tkey_DebReleaseProxStateProcess },
#else
/* 3 */ { TSL_STATEMASK_DEB_RELEASE_PROX, 0 },
#endif
/* 4 */ { TSL_STATEMASK_DEB_RELEASE_DETECT, TSL_tkey_DebReleaseDetectStateProcess },
/* 5 */ { TSL_STATEMASK_DEB_RELEASE_TOUCH, TSL_tkey_DebReleaseTouchStateProcess },
#if TSLPRM_USE_PROX > 0
/* Proximity states */
/* 6 */ { TSL_STATEMASK_PROX, TSL_tkey_ProxStateProcess },
/* 7 */ { TSL_STATEMASK_DEB_PROX, TSL_tkey_DebProxStateProcess },
/* 8 */ { TSL_STATEMASK_DEB_PROX_DETECT, TSL_tkey_DebProxDetectStateProcess },
/* 9 */ { TSL_STATEMASK_DEB_PROX_TOUCH, TSL_tkey_DebProxTouchStateProcess },
#else
/* 6 */ { TSL_STATEMASK_PROX, 0 },
/* 7 */ { TSL_STATEMASK_DEB_PROX, 0 },
/* 8 */ { TSL_STATEMASK_DEB_PROX_DETECT, 0 },
/* 9 */ { TSL_STATEMASK_DEB_PROX_TOUCH, 0 },
#endif
/* Detect states */
/* 10 */ { TSL_STATEMASK_DETECT, TSL_tkey_DetectStateProcess },
/* 11 */ { TSL_STATEMASK_DEB_DETECT, TSL_tkey_DebDetectStateProcess },
/* Touch state */
/* 12 */ { TSL_STATEMASK_TOUCH, TSL_tkey_TouchStateProcess },
/* Error states */
/* 13 */ { TSL_STATEMASK_ERROR, MyTKeys_ErrorStateProcess },
/* 14 */ { TSL_STATEMASK_DEB_ERROR_CALIB, TSL_tkey_DebErrorStateProcess },
/* 15 */ { TSL_STATEMASK_DEB_ERROR_RELEASE, TSL_tkey_DebErrorStateProcess },
/* 16 */ { TSL_STATEMASK_DEB_ERROR_PROX, TSL_tkey_DebErrorStateProcess },
/* 17 */ { TSL_STATEMASK_DEB_ERROR_DETECT, TSL_tkey_DebErrorStateProcess },
/* 18 */ { TSL_STATEMASK_DEB_ERROR_TOUCH, TSL_tkey_DebErrorStateProcess },
/* Other states */
/* 19 */ { TSL_STATEMASK_OFF, MyTKeys_OffStateProcess }
};
/* Methods for "extended" type (ROM) */
CONST TSL_TouchKeyMethods_T MyTKeys_Methods = {
TSL_tkey_Init,
TSL_tkey_Process
};
/* TouchKeys list (ROM) */
CONST TSL_TouchKey_T MyTKeys[TSLPRM_TOTAL_TKEYS] = {
{ &MyTKeys_Data[0], &MyTKeys_Param[0], &MyChannels_Data[CHANNEL_0_DEST], MyTKeys_StateMachine, &MyTKeys_Methods },
{ &MyTKeys_Data[1], &MyTKeys_Param[1], &MyChannels_Data[CHANNEL_1_DEST], MyTKeys_StateMachine, &MyTKeys_Methods },
{ &MyTKeys_Data[2], &MyTKeys_Param[2], &MyChannels_Data[CHANNEL_2_DEST], MyTKeys_StateMachine, &MyTKeys_Methods }
};
/*============================================================================*/
/* Linear and Rotary sensors */
/*============================================================================*/
/* Data (RAM) */
TSL_LinRotData_T MyLinRots_Data[TSLPRM_TOTAL_LINROTS];
/* Parameters (RAM) */
TSL_LinRotParam_T MyLinRots_Param[TSLPRM_TOTAL_LINROTS];
/* State Machine (ROM) */
void MyLinRots_ErrorStateProcess(void);
void MyLinRots_OffStateProcess(void);
CONST TSL_State_T MyLinRots_StateMachine[] = {
/* Calibration states */
/* 0 */ { TSL_STATEMASK_CALIB, TSL_linrot_CalibrationStateProcess },
/* 1 */ { TSL_STATEMASK_DEB_CALIB, TSL_linrot_DebCalibrationStateProcess },
/* Release states */
/* 2 */ { TSL_STATEMASK_RELEASE, TSL_linrot_ReleaseStateProcess },
#if TSLPRM_USE_PROX > 0
/* 3 */ { TSL_STATEMASK_DEB_RELEASE_PROX, TSL_linrot_DebReleaseProxStateProcess },
#else
/* 3 */ { TSL_STATEMASK_DEB_RELEASE_PROX, 0 },
#endif
/* 4 */ { TSL_STATEMASK_DEB_RELEASE_DETECT, TSL_linrot_DebReleaseDetectStateProcess },
/* 5 */ { TSL_STATEMASK_DEB_RELEASE_TOUCH, TSL_linrot_DebReleaseTouchStateProcess },
#if TSLPRM_USE_PROX > 0
/* Proximity states */
/* 6 */ { TSL_STATEMASK_PROX, TSL_linrot_ProxStateProcess },
/* 7 */ { TSL_STATEMASK_DEB_PROX, TSL_linrot_DebProxStateProcess },
/* 8 */ { TSL_STATEMASK_DEB_PROX_DETECT, TSL_linrot_DebProxDetectStateProcess },
/* 9 */ { TSL_STATEMASK_DEB_PROX_TOUCH, TSL_linrot_DebProxTouchStateProcess },
#else
/* 6 */ { TSL_STATEMASK_PROX, 0 },
/* 7 */ { TSL_STATEMASK_DEB_PROX, 0 },
/* 8 */ { TSL_STATEMASK_DEB_PROX_DETECT, 0 },
/* 9 */ { TSL_STATEMASK_DEB_PROX_TOUCH, 0 },
#endif
/* Detect states */
/* 10 */ { TSL_STATEMASK_DETECT, TSL_linrot_DetectStateProcess },
/* 11 */ { TSL_STATEMASK_DEB_DETECT, TSL_linrot_DebDetectStateProcess },
/* Touch state */
/* 12 */ { TSL_STATEMASK_TOUCH, TSL_linrot_TouchStateProcess },
/* Error states */
/* 13 */ { TSL_STATEMASK_ERROR, MyLinRots_ErrorStateProcess },
/* 14 */ { TSL_STATEMASK_DEB_ERROR_CALIB, TSL_linrot_DebErrorStateProcess },
/* 15 */ { TSL_STATEMASK_DEB_ERROR_RELEASE, TSL_linrot_DebErrorStateProcess },
/* 16 */ { TSL_STATEMASK_DEB_ERROR_PROX, TSL_linrot_DebErrorStateProcess },
/* 17 */ { TSL_STATEMASK_DEB_ERROR_DETECT, TSL_linrot_DebErrorStateProcess },
/* 18 */ { TSL_STATEMASK_DEB_ERROR_TOUCH, TSL_linrot_DebErrorStateProcess },
/* Other states */
/* 19 */ { TSL_STATEMASK_OFF, MyLinRots_OffStateProcess }
};
/* Methods for "extended" type (ROM) */
CONST TSL_LinRotMethods_T MyLinRots_Methods = {
TSL_linrot_Init,
TSL_linrot_Process,
TSL_linrot_CalcPos
};
/* Delta Normalization Process
The MSB is the integer part, the LSB is the real part
Examples:
- To apply a factor 1.10:
0x01 to the MSB
0x1A to the LSB (0.10 x 256 = 25.6 -> rounded to 26 = 0x1A)
- To apply a factor 0.90:
0x00 to the MSB
0xE6 to the LSB (0.90 x 256 = 230.4 -> rounded to 230 = 0xE6)
*/
CONST uint16_t MyLinRot0_DeltaCoeff[3] = {0x0100, 0x0100, 0x0100};
/* LinRots list (ROM)*/
CONST TSL_LinRot_T MyLinRots[TSLPRM_TOTAL_LINROTS] = {
{
/* LinRot sensor 0 = S1 */
&MyLinRots_Data[0],
&MyLinRots_Param[0],
&MyChannels_Data[CHANNEL_3_DEST], // first channel data
5, /* Number of channels */ //
MyLinRot0_DeltaCoeff,
// discovery
// (TSL_tsignPosition_T *)TSL_POSOFF_3CH_LIN_H,
// GP board
(TSL_tsignPosition_T *)TSL_POSOFF_5CH_LIN_M1,
// Discovery
// TSL_SCTCOMP_3CH_LIN_H,
// GP board
TSL_SCTCOMP_5CH_LIN_M1,
// Discovery
// TSL_POSCORR_3CH_LIN_H,
// GP board
TSL_POSCORR_5CH_LIN_M1,
MyLinRots_StateMachine,
&MyLinRots_Methods
}
};
/*============================================================================*/
/* Generic Objects */
/*============================================================================*/
/* List (ROM) */
CONST TSL_Object_T MyObjects[TSLPRM_TOTAL_OBJECTS] = {
// touchkeys
{ TSL_OBJ_TOUCHKEY, (TSL_TouchKey_T *)&MyTKeys[0] },
{ TSL_OBJ_TOUCHKEY, (TSL_TouchKey_T *)&MyTKeys[1] },
{ TSL_OBJ_TOUCHKEY, (TSL_TouchKey_T *)&MyTKeys[2] },
// lin rot
{ TSL_OBJ_LINEAR, (TSL_LinRot_T *)&MyLinRots[0] }
};
/* Group (RAM) */
TSL_ObjectGroup_T MyObjGroup = {
&MyObjects[0], /* First object */
TSLPRM_TOTAL_OBJECTS, /* Number of objects */
0x00, /* State mask reset value */
TSL_STATE_NOT_CHANGED /* Current state */
};
/*============================================================================*/
/* TSL Common Parameters placed in RAM or ROM */
/* --> external declaration in tsl_conf.h */
/*============================================================================*/
TSL_Params_T TSL_Params = {
TSLPRM_ACQ_MIN,
TSLPRM_ACQ_MAX,
TSLPRM_CALIB_SAMPLES,
TSLPRM_DTO,
#if TSLPRM_TOTAL_TKEYS > 0
MyTKeys_StateMachine, /* Default state machine for TKeys */
&MyTKeys_Methods, /* Default methods for TKeys */
#endif
#if TSLPRM_TOTAL_LNRTS > 0
MyLinRots_StateMachine, /* Default state machine for LinRots */
&MyLinRots_Methods /* Default methods for LinRots */
#endif
};
/* Private functions prototype -----------------------------------------------*/
/* Global variables ----------------------------------------------------------*/
__IO TSL_tTick_ms_T ECSLastTick; /* Hold the last time value for ECS */
/**
* @brief Initialize the STMTouch Driver
* @param None
* @retval None
*/
void tsl_user_Init(void) {
TSL_obj_GroupInit(&MyObjGroup); /* Init Objects */
TSL_Init(MyBanks); /* Init acquisition module */
tsl_user_SetThresholds(); /* Init thresholds for each object individually (optional) */
}
/**
* @brief Execute STMTouch Driver main State machine
* @param None
* @retval status Return TSL_STATUS_OK if the acquisition is done
*/
tsl_user_status_t tsl_user_Exec(void)
{
static uint32_t idx_bank = 0;
static uint32_t config_done = 0;
tsl_user_status_t status = TSL_USER_STATUS_BUSY;
/* Configure and start bank acquisition */
if (!config_done)
{
TSL_acq_BankConfig(idx_bank);
TSL_acq_BankStartAcq();
config_done = 1;
}
/* Check end of acquisition (polling mode) and read result */
if (TSL_acq_BankWaitEOC() == TSL_STATUS_OK) {
TSL_acq_BankGetResult(idx_bank, 0, 0);
idx_bank++; /* Next bank */
config_done = 0;
}
/* Process objects, DxS and ECS
Check if all banks have been acquired
*/
if (idx_bank > TSLPRM_TOTAL_BANKS-1)
{
/* Reset flags for next banks acquisition */
idx_bank = 0;
config_done = 0;
/* Process Objects */
TSL_obj_GroupProcess(&MyObjGroup);
/* DxS processing (if TSLPRM_USE_DXS option is set) */
TSL_dxs_FirstObj(&MyObjGroup);
/* ECS every 100ms */
if (TSL_tim_CheckDelay_ms(100, &ECSLastTick) == TSL_STATUS_OK)
{
if (TSL_ecs_Process(&MyObjGroup) == TSL_STATUS_OK)
{
status = TSL_USER_STATUS_OK_ECS_ON;
}
else
{
status = TSL_USER_STATUS_OK_ECS_OFF;
}
}
else
{
status = TSL_USER_STATUS_OK_NO_ECS;
}
}
else
{
status = TSL_USER_STATUS_BUSY;
}
return status;
}
/**
* @brief Set thresholds for each object (optional).
* @param None
* @retval None
*/
void tsl_user_SetThresholds(void)
{
/* Example: Decrease the Detect thresholds for the TKEY 0
MyTKeys_Param[0].DetectInTh -= 10;
MyTKeys_Param[0].DetectOutTh -= 10;
*/
}
/**
* @brief Executed when a sensor is in Error state
* @param None
* @retval None
*/
void MyTKeys_ErrorStateProcess(void)
{
/* Add here your own processing when a sensor is in Error state */
}
/**
* @brief Executed when a sensor is in Off state
* @param None
* @retval None
*/
void MyTKeys_OffStateProcess(void)
{
/* Add here your own processing when a sensor is in Off state */
}
/**
* @brief Executed when a sensor is in Error state
* @param None
* @retval None
*/
void MyLinRots_ErrorStateProcess(void)
{
/* Add here your own processing when a sensor is in Error state */
}
/**
* @brief Executed when a sensor is in Off state
* @param None
* @retval None
*/
void MyLinRots_OffStateProcess(void)
{
/* Add here your own processing when a sensor is in Off state */
}
/**
* @brief This function handles a tick.
* @param None
* @retval None
*/
void User_Tick_Management(void) {
// tick counters set to zero first time this routine is called
static uint32_t tempo_50ms=0;
static uint32_t tempo_100ms=0;
static uint32_t tempo_200ms=0;
static uint32_t tempo_300ms=0;
static uint32_t tempo_400ms=0;
static uint32_t tempo_500ms=0;
// increment each counter, but bound to max count for each
tempo_50ms++;
tempo_100ms++;
tempo_200ms++;
tempo_300ms++;
tempo_400ms++;
tempo_500ms++;
tempo_50ms%=50;
tempo_100ms%=100;
tempo_200ms%=200;
tempo_300ms%=300;
tempo_400ms%=400;
tempo_500ms%=500;
// LINEAR_POSITION = MyLinRots[0].p_Data->Position
// above is a "scaled" position
// MyLinRots[0].p_Data->RawPosition
if (LINEAR_DETECT) {
// Now we just adjust when we are touching.
if (LINEAR_POSITION < 4) {
if (tempo_500ms==0) {
BSP_LED_Toggle(LED2);
}
} else if (LINEAR_POSITION < 8) {
if (tempo_300ms==0) {
BSP_LED_Toggle(LED2);
}
} else if (LINEAR_POSITION < 12) {
if (tempo_100ms==0) {
BSP_LED_Toggle(LED2);
}
} else { // pos >= 12
if (tempo_50ms==0) {
BSP_LED_Toggle(LED2);
}
}
}
}
/**
* @brief Display sensors information on LEDs and LCD
* @param status TSL user status
* @retval None
*/
void Process_Sensors(tsl_user_status_t status) {
/* LED1 is ON when TS1 on board is touched */
if (MyTKeys[0].p_Data->StateId == TSL_STATEID_DETECT){
BSP_LED_On(LED3);
} else {
BSP_LED_Off(LED3);
}
/* LED2 is ON when TS2 on board is touched */
if (MyTKeys[1].p_Data->StateId == TSL_STATEID_DETECT) {
BSP_LED_On(LED4);
} else {
BSP_LED_Off(LED4);
}
/* LED3 is ON when TS3 on board is touched */
if (MyTKeys[2].p_Data->StateId == TSL_STATEID_DETECT) {
BSP_LED_On(LED5);
} else {
BSP_LED_Off(LED5);
}
#ifdef isthisused
/* ECS information */
switch (status){
case TSL_USER_STATUS_OK_ECS_OFF:
BSP_LED_Off(LED5);
break;
case TSL_USER_STATUS_OK_ECS_ON:
BSP_LED_Toggle(LED5);
break;
default:
break;
}
#endif
if (LINEAR_DETECT) {
BSP_LED_On(LED1);
} else{
BSP_LED_Off(LED1);
}
}
感谢任何帮助。
事实证明,线性传感器需要单个 io 与传感器的每个组件的单个采样电容器配对。上面的问题是硬件设计为两组五个 io,带有两个采样电容器。一组的抽样上限为 3 ios,另一组的抽样上限为 2 ios.
我换了两个三通道组,每个通道组有一个io和一个sampling cap。之后代码运行良好。
// The three linrot channels
#define CHANNEL_0_IO_MSK (TSC_GROUP1_IO3)
#define CHANNEL_0_GRP_MSK (TSC_GROUP1)
#define CHANNEL_0_SRC (TSC_GROUP1_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_0_DEST (0) /* Index in destination result array */
#define CHANNEL_1_IO_MSK (TSC_GROUP2_IO4)
#define CHANNEL_1_GRP_MSK (TSC_GROUP2)
#define CHANNEL_1_SRC (TSC_GROUP2_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_1_DEST (1) /* Index in destination result array */
#define CHANNEL_2_IO_MSK (TSC_GROUP3_IO2)
#define CHANNEL_2_GRP_MSK (TSC_GROUP3)
#define CHANNEL_2_SRC (TSC_GROUP3_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_2_DEST (2) /* Index in destination result array */
我遇到过这种情况,我试图在软件而不是硬件上找到解决方案。此问题不是硬件问题,因为如果您尝试读取同一组和同一组中的通道,增量值将彼此相同。
我想,您在STMStudio中的读数如下:MyChannels_Data[3].Delta = MyChannels_Data[4].Delta
和MyChannels_Data[5].Delta = MyChannels_Data[6].Delta = MyChannels_Data[7].Delta
。
为了解决这个问题,您应该将您的 BANK_3 (LinRot Bank) 分开如下:
头文件:
// The linrot banks
// Channel 3 is a Group1_IO
#define BANK_3_NBCHANNELS (1)
#define BANK_3_MSK_CHANNELS (CHANNEL_3_IO_MSK | SHIELD_IO_MSK)
#define BANK_3_MSK_GROUPS (CHANNEL_3_GRP_MSK)
// Channel 4 is a Group1_IO, so I have to separate it from Bank 3, because Channel 3 is also a Group1_IO.
// Channel 5 is a Group2_IO, so I can combine it with Channel 4 in same Bank.
#define BANK_4_NBCHANNELS (2)
#define BANK_4_MSK_CHANNELS (CHANNEL_4_IO_MSK | CHANNEL_5_IO_MSK | SHIELD_IO_MSK)
#define BANK_4_MSK_GROUPS (CHANNEL_4_GRP_MSK | CHANNEL_5_GRP_MSK )
// Channel 6 is a Group2_IO, so I have to separate it from Bank 4 because Channel 5 is also a Group2_IO.
#define BANK_5_NBCHANNELS (1)
#define BANK_5_MSK_CHANNELS (CHANNEL_6_IO_MSK | SHIELD_IO_MSK)
#define BANK_5_MSK_GROUPS (CHANNEL_6_GRP_MSK)
// Channel 7 is a Group2_IO, so I have to separate it from Bank 6,
// because Channel 6 is also a Group2_IO.
#define BANK_6_NBCHANNELS (1)
#define BANK_6_MSK_CHANNELS (CHANNEL_7_IO_MSK | SHIELD_IO_MSK)
#define BANK_6_MSK_GROUPS (CHANNEL_7_GRP_MSK)
源文件:
/*============================================================================*/
/* Banks */
/*============================================================================*/
/* List (ROM) */
CONST TSL_Bank_T MyBanks[TSLPRM_TOTAL_BANKS] = {
// The three touchkey bankss
{&MyChannels_Src[0], &MyChannels_Dest[0], MyChannels_Data, BANK_0_NBCHANNELS, BANK_0_MSK_CHANNELS, BANK_0_MSK_GROUPS},
{&MyChannels_Src[1], &MyChannels_Dest[1], MyChannels_Data, BANK_1_NBCHANNELS, BANK_1_MSK_CHANNELS, BANK_1_MSK_GROUPS},
{&MyChannels_Src[2], &MyChannels_Dest[2], MyChannels_Data, BANK_2_NBCHANNELS, BANK_2_MSK_CHANNELS, BANK_2_MSK_GROUPS},
// The one linrot bank
{&MyChannels_Src[3], &MyChannels_Dest[3], MyChannels_Data, BANK_3_NBCHANNELS, BANK_3_MSK_CHANNELS, BANK_3_MSK_GROUPS},
{&MyChannels_Src[4], &MyChannels_Dest[4], MyChannels_Data, BANK_4_NBCHANNELS, BANK_4_MSK_CHANNELS, BANK_4_MSK_GROUPS},
{&MyChannels_Src[6], &MyChannels_Dest[6], MyChannels_Data, BANK_5_NBCHANNELS, BANK_5_MSK_CHANNELS, BANK_5_MSK_GROUPS},
{&MyChannels_Src[7], &MyChannels_Dest[7], MyChannels_Data, BANK_6_NBCHANNELS, BANK_6_MSK_CHANNELS, BANK_6_MSK_GROUPS},
};
配置文件:
#define TSLPRM_TOTAL_BANKS (7)
注意:图书馆的银行数量有限制。在我的例子中,我的申请中要求的银行数量超过了限制,然后我只是改变了这个值,我没有遇到任何问题。
回答有点晚了。但我希望它能有所帮助。
编辑:我在"UM1606 - STMTouch driver user manual"文档第122页找到了银行定义的提示,解释如下:
For optimum sensitivity and position reporting, all the channels
composing a linear or a rotary touch sensor must be acquired
simultaneously. This means that all the channels must belong to the
same bank.
Note:The library allows to define a linear or a rotary touch sensor
with channels belonging to different banks. A such configuration
induces a loss of sensitivity and a higher noise level. Moreover,
depending on the acquisition time, it is also possible to observe a
position change when removing the finger from the sensor.
For optimum performance of a linear or rotary sensor, all channels of
such a sensor must be acquired simultaneously.Therefore all channels
must belong to the same bank, which means the I/Os must be selected
from different analog I/O groups. Please refer to datasheet for more
information regarding I/O groups and available capacitive sensing
GPIOs.
总结:如果同一组I/Os不能在同一组中,如果传感器的所有通道都应在同一组中,则传感器的所有通道应属于不同的组。假设传感器是一个 6 通道线性传感器,那么通道可以连接如下:1-Ch = Group1_IO1,2-Ch = Group2_IO1,3-Ch = Group3_IO1, 4-Ch = Group4_IO1、5-Ch = Group5_IO1、6-Ch = Group6_IO1。因此,我们可以很容易地说硬件方案是更好的方案。但不要忘记软件解决方案也存在。但是,它没有那么敏感。
我正在使用一个定制板,它有 8 个通道,由三个触摸键和一个线性传感器组成。
有 8 个通道 IOs、三个采样 IOs 并且没有屏蔽配置。其中三个通道用于三个触摸键。其中五个通道用于线性传感器。
我使用过 STM3270B 探索板,它在 Half-Ended 电极设计 (LIN_H) 中设置了三个通道。我已经完成了该板提供的非中断实现示例。
我使用过 STM3207 评估板,它有两个通道设置为两个触摸键。
在我的定制板上,触摸键工作完美。五通道线性传感器不能完全工作。所有五个垫确实检测到触摸,但就数据位置而言,它失败了。该示例在单个通道中包含所有 ios。据我所知,没有一个示例使用 5 个通道,分为两个 TSC 组。 STMTouch Driver 用户手册中提到了它,但我将不得不再次查找代码示例。
问题在于确定传感器值的宏 LINEAR_POSITION = MyLinRots[0].p_Data->Position 有两个结果。如果与组 1 IOs 关联的两个打击垫中的任何一个被触摸,检测宏将正确触发,但 LINEAR_POSITION 值为 0x2。同样,如果与组 2 IOS 关联的三个打击垫被触摸,检测宏会正确触发,但 LINEAR_POSITION 值为 0xC。
我认为每个垫的值会在 0 到 255 之间变化,分为 5 种方式。我查看了原始位置而不是缩放后的位置,但它的行为类似。
这是我的频道、库、触摸键布局,linear/rotary 和 objects 分布在 header 文件和源文件中。
header:
/* Channel IOs definition */
// The three touchkey channels
#define CHANNEL_0_IO_MSK (TSC_GROUP6_IO2)
#define CHANNEL_0_GRP_MSK (TSC_GROUP6)
#define CHANNEL_0_SRC (TSC_GROUP6_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_0_DEST (0) /* Index in destination result array */
#define CHANNEL_1_IO_MSK (TSC_GROUP6_IO3)
#define CHANNEL_1_GRP_MSK (TSC_GROUP6)
#define CHANNEL_1_SRC (TSC_GROUP6_IDX)
#define CHANNEL_1_DEST (1)
#define CHANNEL_2_IO_MSK (TSC_GROUP6_IO4)
#define CHANNEL_2_GRP_MSK (TSC_GROUP6)
#define CHANNEL_2_SRC (TSC_GROUP6_IDX)
#define CHANNEL_2_DEST (2)
// The five linrot channels
#define CHANNEL_3_IO_MSK (TSC_GROUP1_IO3)
#define CHANNEL_3_GRP_MSK (TSC_GROUP1)
#define CHANNEL_3_SRC (TSC_GROUP1_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_3_DEST (3) /* Index in destination result array */
#define CHANNEL_4_IO_MSK (TSC_GROUP1_IO4)
#define CHANNEL_4_GRP_MSK (TSC_GROUP1)
#define CHANNEL_4_SRC (TSC_GROUP1_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_4_DEST (4) /* Index in destination result array */
#define CHANNEL_5_IO_MSK (TSC_GROUP2_IO2)
#define CHANNEL_5_GRP_MSK (TSC_GROUP2)
#define CHANNEL_5_SRC (TSC_GROUP2_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_5_DEST (5) /* Index in destination result array */
#define CHANNEL_6_IO_MSK (TSC_GROUP2_IO3)
#define CHANNEL_6_GRP_MSK (TSC_GROUP2)
#define CHANNEL_6_SRC (TSC_GROUP2_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_6_DEST (6) /* Index in destination result array */
#define CHANNEL_7_IO_MSK (TSC_GROUP2_IO4)
#define CHANNEL_7_GRP_MSK (TSC_GROUP2)
#define CHANNEL_7_SRC (TSC_GROUP2_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_7_DEST (7) /* Index in destination result array */
/* Shield IOs definition */
#define SHIELD_IO_MSK (0) // orig (TSC_GROUP7_IO3) we dont have a shield
/* Banks definition */
// The touch key bank
#define BANK_0_NBCHANNELS (1)
#define BANK_0_MSK_CHANNELS (CHANNEL_0_IO_MSK | SHIELD_IO_MSK)
#define BANK_0_MSK_GROUPS (CHANNEL_0_GRP_MSK)
#define BANK_1_NBCHANNELS (1)
#define BANK_1_MSK_CHANNELS (CHANNEL_1_IO_MSK | SHIELD_IO_MSK)
#define BANK_1_MSK_GROUPS (CHANNEL_1_GRP_MSK)
#define BANK_2_NBCHANNELS (1)
#define BANK_2_MSK_CHANNELS (CHANNEL_2_IO_MSK | SHIELD_IO_MSK)
#define BANK_2_MSK_GROUPS (CHANNEL_2_GRP_MSK)
// The linrot bank
#define BANK_3_NBCHANNELS (5)
#define BANK_3_MSK_CHANNELS (CHANNEL_3_IO_MSK | CHANNEL_4_IO_MSK | CHANNEL_5_IO_MSK | CHANNEL_6_IO_MSK| CHANNEL_7_IO_MSK | SHIELD_IO_MSK)
#define BANK_3_MSK_GROUPS (CHANNEL_3_GRP_MSK | CHANNEL_4_GRP_MSK | CHANNEL_5_GRP_MSK | CHANNEL_6_GRP_MSK | CHANNEL_7_GRP_MSK )
设置定义的源文件
/* define for the linear */
#define LINEAR_DETECT ((MyLinRots[0].p_Data->StateId == TSL_STATEID_DETECT) || \
(MyLinRots[0].p_Data->StateId == TSL_STATEID_DEB_RELEASE_DETECT))
#define LINEAR_POSITION (MyLinRots[0].p_Data->Position)
/*============================================================================*/
/* Channels */
/*============================================================================*/
/* Source and Configuration (ROM) */
CONST TSL_ChannelSrc_T MyChannels_Src[TSLPRM_TOTAL_CHANNELS] = {
// The three touchkey channels
{ CHANNEL_0_SRC, CHANNEL_0_IO_MSK, CHANNEL_0_GRP_MSK },
{ CHANNEL_1_SRC, CHANNEL_1_IO_MSK, CHANNEL_1_GRP_MSK },
{ CHANNEL_2_SRC, CHANNEL_2_IO_MSK, CHANNEL_2_GRP_MSK },
// The five linrot channels
{ CHANNEL_3_SRC, CHANNEL_3_IO_MSK, CHANNEL_3_GRP_MSK },
{ CHANNEL_4_SRC, CHANNEL_4_IO_MSK, CHANNEL_4_GRP_MSK },
{ CHANNEL_5_SRC, CHANNEL_5_IO_MSK, CHANNEL_5_GRP_MSK },
{ CHANNEL_6_SRC, CHANNEL_6_IO_MSK, CHANNEL_6_GRP_MSK },
{ CHANNEL_7_SRC, CHANNEL_7_IO_MSK, CHANNEL_7_GRP_MSK }
};
/* Destination (ROM) */
CONST TSL_ChannelDest_T MyChannels_Dest[TSLPRM_TOTAL_CHANNELS] = {
// The three touchkey channels
{ CHANNEL_0_DEST },
{ CHANNEL_1_DEST },
{ CHANNEL_2_DEST },
// The five linrot channels
{ CHANNEL_3_DEST },
{ CHANNEL_4_DEST },
{ CHANNEL_5_DEST },
{ CHANNEL_6_DEST },
{ CHANNEL_7_DEST },
};
/* Data (RAM) */
TSL_ChannelData_T MyChannels_Data[TSLPRM_TOTAL_CHANNELS];
/*============================================================================*/
/* Banks */
/*============================================================================*/
/* List (ROM) */
CONST TSL_Bank_T MyBanks[TSLPRM_TOTAL_BANKS] = {
// The three touchkey bankss
{&MyChannels_Src[0], &MyChannels_Dest[0], MyChannels_Data, BANK_0_NBCHANNELS, BANK_0_MSK_CHANNELS, BANK_0_MSK_GROUPS},
{&MyChannels_Src[1], &MyChannels_Dest[1], MyChannels_Data, BANK_1_NBCHANNELS, BANK_1_MSK_CHANNELS, BANK_1_MSK_GROUPS},
{&MyChannels_Src[2], &MyChannels_Dest[2], MyChannels_Data, BANK_2_NBCHANNELS, BANK_2_MSK_CHANNELS, BANK_2_MSK_GROUPS},
// The one linrot bank
{&MyChannels_Src[3], &MyChannels_Dest[3], MyChannels_Data, BANK_3_NBCHANNELS, BANK_3_MSK_CHANNELS, BANK_3_MSK_GROUPS}
};
/*============================================================================*/
/* Touchkey sensors */
/*============================================================================*/
/* Data (RAM) */
TSL_TouchKeyData_T MyTKeys_Data[TSLPRM_TOTAL_TKEYS];
/* Parameters (RAM) */
TSL_TouchKeyParam_T MyTKeys_Param[TSLPRM_TOTAL_TKEYS];
/* State Machine (ROM) */
void MyTKeys_ErrorStateProcess(void);
void MyTKeys_OffStateProcess(void);
CONST TSL_State_T MyTKeys_StateMachine[] = {
/* Calibration states */
/* 0 */ { TSL_STATEMASK_CALIB, TSL_tkey_CalibrationStateProcess },
/* 1 */ { TSL_STATEMASK_DEB_CALIB, TSL_tkey_DebCalibrationStateProcess },
/* Release states */
/* 2 */ { TSL_STATEMASK_RELEASE, TSL_tkey_ReleaseStateProcess },
#if TSLPRM_USE_PROX > 0
/* 3 */ { TSL_STATEMASK_DEB_RELEASE_PROX, TSL_tkey_DebReleaseProxStateProcess },
#else
/* 3 */ { TSL_STATEMASK_DEB_RELEASE_PROX, 0 },
#endif
/* 4 */ { TSL_STATEMASK_DEB_RELEASE_DETECT, TSL_tkey_DebReleaseDetectStateProcess },
/* 5 */ { TSL_STATEMASK_DEB_RELEASE_TOUCH, TSL_tkey_DebReleaseTouchStateProcess },
#if TSLPRM_USE_PROX > 0
/* Proximity states */
/* 6 */ { TSL_STATEMASK_PROX, TSL_tkey_ProxStateProcess },
/* 7 */ { TSL_STATEMASK_DEB_PROX, TSL_tkey_DebProxStateProcess },
/* 8 */ { TSL_STATEMASK_DEB_PROX_DETECT, TSL_tkey_DebProxDetectStateProcess },
/* 9 */ { TSL_STATEMASK_DEB_PROX_TOUCH, TSL_tkey_DebProxTouchStateProcess },
#else
/* 6 */ { TSL_STATEMASK_PROX, 0 },
/* 7 */ { TSL_STATEMASK_DEB_PROX, 0 },
/* 8 */ { TSL_STATEMASK_DEB_PROX_DETECT, 0 },
/* 9 */ { TSL_STATEMASK_DEB_PROX_TOUCH, 0 },
#endif
/* Detect states */
/* 10 */ { TSL_STATEMASK_DETECT, TSL_tkey_DetectStateProcess },
/* 11 */ { TSL_STATEMASK_DEB_DETECT, TSL_tkey_DebDetectStateProcess },
/* Touch state */
/* 12 */ { TSL_STATEMASK_TOUCH, TSL_tkey_TouchStateProcess },
/* Error states */
/* 13 */ { TSL_STATEMASK_ERROR, MyTKeys_ErrorStateProcess },
/* 14 */ { TSL_STATEMASK_DEB_ERROR_CALIB, TSL_tkey_DebErrorStateProcess },
/* 15 */ { TSL_STATEMASK_DEB_ERROR_RELEASE, TSL_tkey_DebErrorStateProcess },
/* 16 */ { TSL_STATEMASK_DEB_ERROR_PROX, TSL_tkey_DebErrorStateProcess },
/* 17 */ { TSL_STATEMASK_DEB_ERROR_DETECT, TSL_tkey_DebErrorStateProcess },
/* 18 */ { TSL_STATEMASK_DEB_ERROR_TOUCH, TSL_tkey_DebErrorStateProcess },
/* Other states */
/* 19 */ { TSL_STATEMASK_OFF, MyTKeys_OffStateProcess }
};
/* Methods for "extended" type (ROM) */
CONST TSL_TouchKeyMethods_T MyTKeys_Methods = {
TSL_tkey_Init,
TSL_tkey_Process
};
/* TouchKeys list (ROM) */
CONST TSL_TouchKey_T MyTKeys[TSLPRM_TOTAL_TKEYS] = {
{ &MyTKeys_Data[0], &MyTKeys_Param[0], &MyChannels_Data[CHANNEL_0_DEST], MyTKeys_StateMachine, &MyTKeys_Methods },
{ &MyTKeys_Data[1], &MyTKeys_Param[1], &MyChannels_Data[CHANNEL_1_DEST], MyTKeys_StateMachine, &MyTKeys_Methods },
{ &MyTKeys_Data[2], &MyTKeys_Param[2], &MyChannels_Data[CHANNEL_2_DEST], MyTKeys_StateMachine, &MyTKeys_Methods }
};
/*============================================================================*/
/* Linear and Rotary sensors */
/*============================================================================*/
/* Data (RAM) */
TSL_LinRotData_T MyLinRots_Data[TSLPRM_TOTAL_LINROTS];
/* Parameters (RAM) */
TSL_LinRotParam_T MyLinRots_Param[TSLPRM_TOTAL_LINROTS];
/* State Machine (ROM) */
void MyLinRots_ErrorStateProcess(void);
void MyLinRots_OffStateProcess(void);
CONST TSL_State_T MyLinRots_StateMachine[] = {
/* Calibration states */
/* 0 */ { TSL_STATEMASK_CALIB, TSL_linrot_CalibrationStateProcess },
/* 1 */ { TSL_STATEMASK_DEB_CALIB, TSL_linrot_DebCalibrationStateProcess },
/* Release states */
/* 2 */ { TSL_STATEMASK_RELEASE, TSL_linrot_ReleaseStateProcess },
#if TSLPRM_USE_PROX > 0
/* 3 */ { TSL_STATEMASK_DEB_RELEASE_PROX, TSL_linrot_DebReleaseProxStateProcess },
#else
/* 3 */ { TSL_STATEMASK_DEB_RELEASE_PROX, 0 },
#endif
/* 4 */ { TSL_STATEMASK_DEB_RELEASE_DETECT, TSL_linrot_DebReleaseDetectStateProcess },
/* 5 */ { TSL_STATEMASK_DEB_RELEASE_TOUCH, TSL_linrot_DebReleaseTouchStateProcess },
#if TSLPRM_USE_PROX > 0
/* Proximity states */
/* 6 */ { TSL_STATEMASK_PROX, TSL_linrot_ProxStateProcess },
/* 7 */ { TSL_STATEMASK_DEB_PROX, TSL_linrot_DebProxStateProcess },
/* 8 */ { TSL_STATEMASK_DEB_PROX_DETECT, TSL_linrot_DebProxDetectStateProcess },
/* 9 */ { TSL_STATEMASK_DEB_PROX_TOUCH, TSL_linrot_DebProxTouchStateProcess },
#else
/* 6 */ { TSL_STATEMASK_PROX, 0 },
/* 7 */ { TSL_STATEMASK_DEB_PROX, 0 },
/* 8 */ { TSL_STATEMASK_DEB_PROX_DETECT, 0 },
/* 9 */ { TSL_STATEMASK_DEB_PROX_TOUCH, 0 },
#endif
/* Detect states */
/* 10 */ { TSL_STATEMASK_DETECT, TSL_linrot_DetectStateProcess },
/* 11 */ { TSL_STATEMASK_DEB_DETECT, TSL_linrot_DebDetectStateProcess },
/* Touch state */
/* 12 */ { TSL_STATEMASK_TOUCH, TSL_linrot_TouchStateProcess },
/* Error states */
/* 13 */ { TSL_STATEMASK_ERROR, MyLinRots_ErrorStateProcess },
/* 14 */ { TSL_STATEMASK_DEB_ERROR_CALIB, TSL_linrot_DebErrorStateProcess },
/* 15 */ { TSL_STATEMASK_DEB_ERROR_RELEASE, TSL_linrot_DebErrorStateProcess },
/* 16 */ { TSL_STATEMASK_DEB_ERROR_PROX, TSL_linrot_DebErrorStateProcess },
/* 17 */ { TSL_STATEMASK_DEB_ERROR_DETECT, TSL_linrot_DebErrorStateProcess },
/* 18 */ { TSL_STATEMASK_DEB_ERROR_TOUCH, TSL_linrot_DebErrorStateProcess },
/* Other states */
/* 19 */ { TSL_STATEMASK_OFF, MyLinRots_OffStateProcess }
};
/* Methods for "extended" type (ROM) */
CONST TSL_LinRotMethods_T MyLinRots_Methods = {
TSL_linrot_Init,
TSL_linrot_Process,
TSL_linrot_CalcPos
};
/* Delta Normalization Process
The MSB is the integer part, the LSB is the real part
Examples:
- To apply a factor 1.10:
0x01 to the MSB
0x1A to the LSB (0.10 x 256 = 25.6 -> rounded to 26 = 0x1A)
- To apply a factor 0.90:
0x00 to the MSB
0xE6 to the LSB (0.90 x 256 = 230.4 -> rounded to 230 = 0xE6)
*/
CONST uint16_t MyLinRot0_DeltaCoeff[3] = {0x0100, 0x0100, 0x0100};
/* LinRots list (ROM)*/
CONST TSL_LinRot_T MyLinRots[TSLPRM_TOTAL_LINROTS] = {
{
/* LinRot sensor 0 = S1 */
&MyLinRots_Data[0],
&MyLinRots_Param[0],
&MyChannels_Data[CHANNEL_3_DEST], // first channel data
5, /* Number of channels */ //
MyLinRot0_DeltaCoeff,
// discovery
// (TSL_tsignPosition_T *)TSL_POSOFF_3CH_LIN_H,
// GP board
(TSL_tsignPosition_T *)TSL_POSOFF_5CH_LIN_M1,
// Discovery
// TSL_SCTCOMP_3CH_LIN_H,
// GP board
TSL_SCTCOMP_5CH_LIN_M1,
// Discovery
// TSL_POSCORR_3CH_LIN_H,
// GP board
TSL_POSCORR_5CH_LIN_M1,
MyLinRots_StateMachine,
&MyLinRots_Methods
}
};
/*============================================================================*/
/* Generic Objects */
/*============================================================================*/
/* List (ROM) */
CONST TSL_Object_T MyObjects[TSLPRM_TOTAL_OBJECTS] = {
// touchkeys
{ TSL_OBJ_TOUCHKEY, (TSL_TouchKey_T *)&MyTKeys[0] },
{ TSL_OBJ_TOUCHKEY, (TSL_TouchKey_T *)&MyTKeys[1] },
{ TSL_OBJ_TOUCHKEY, (TSL_TouchKey_T *)&MyTKeys[2] },
// lin rot
{ TSL_OBJ_LINEAR, (TSL_LinRot_T *)&MyLinRots[0] }
};
/* Group (RAM) */
TSL_ObjectGroup_T MyObjGroup = {
&MyObjects[0], /* First object */
TSLPRM_TOTAL_OBJECTS, /* Number of objects */
0x00, /* State mask reset value */
TSL_STATE_NOT_CHANGED /* Current state */
};
/*============================================================================*/
/* TSL Common Parameters placed in RAM or ROM */
/* --> external declaration in tsl_conf.h */
/*============================================================================*/
TSL_Params_T TSL_Params = {
TSLPRM_ACQ_MIN,
TSLPRM_ACQ_MAX,
TSLPRM_CALIB_SAMPLES,
TSLPRM_DTO,
#if TSLPRM_TOTAL_TKEYS > 0
MyTKeys_StateMachine, /* Default state machine for TKeys */
&MyTKeys_Methods, /* Default methods for TKeys */
#endif
#if TSLPRM_TOTAL_LNRTS > 0
MyLinRots_StateMachine, /* Default state machine for LinRots */
&MyLinRots_Methods /* Default methods for LinRots */
#endif
};
/* Private functions prototype -----------------------------------------------*/
/* Global variables ----------------------------------------------------------*/
__IO TSL_tTick_ms_T ECSLastTick; /* Hold the last time value for ECS */
/**
* @brief Initialize the STMTouch Driver
* @param None
* @retval None
*/
void tsl_user_Init(void) {
TSL_obj_GroupInit(&MyObjGroup); /* Init Objects */
TSL_Init(MyBanks); /* Init acquisition module */
tsl_user_SetThresholds(); /* Init thresholds for each object individually (optional) */
}
/**
* @brief Execute STMTouch Driver main State machine
* @param None
* @retval status Return TSL_STATUS_OK if the acquisition is done
*/
tsl_user_status_t tsl_user_Exec(void)
{
static uint32_t idx_bank = 0;
static uint32_t config_done = 0;
tsl_user_status_t status = TSL_USER_STATUS_BUSY;
/* Configure and start bank acquisition */
if (!config_done)
{
TSL_acq_BankConfig(idx_bank);
TSL_acq_BankStartAcq();
config_done = 1;
}
/* Check end of acquisition (polling mode) and read result */
if (TSL_acq_BankWaitEOC() == TSL_STATUS_OK) {
TSL_acq_BankGetResult(idx_bank, 0, 0);
idx_bank++; /* Next bank */
config_done = 0;
}
/* Process objects, DxS and ECS
Check if all banks have been acquired
*/
if (idx_bank > TSLPRM_TOTAL_BANKS-1)
{
/* Reset flags for next banks acquisition */
idx_bank = 0;
config_done = 0;
/* Process Objects */
TSL_obj_GroupProcess(&MyObjGroup);
/* DxS processing (if TSLPRM_USE_DXS option is set) */
TSL_dxs_FirstObj(&MyObjGroup);
/* ECS every 100ms */
if (TSL_tim_CheckDelay_ms(100, &ECSLastTick) == TSL_STATUS_OK)
{
if (TSL_ecs_Process(&MyObjGroup) == TSL_STATUS_OK)
{
status = TSL_USER_STATUS_OK_ECS_ON;
}
else
{
status = TSL_USER_STATUS_OK_ECS_OFF;
}
}
else
{
status = TSL_USER_STATUS_OK_NO_ECS;
}
}
else
{
status = TSL_USER_STATUS_BUSY;
}
return status;
}
/**
* @brief Set thresholds for each object (optional).
* @param None
* @retval None
*/
void tsl_user_SetThresholds(void)
{
/* Example: Decrease the Detect thresholds for the TKEY 0
MyTKeys_Param[0].DetectInTh -= 10;
MyTKeys_Param[0].DetectOutTh -= 10;
*/
}
/**
* @brief Executed when a sensor is in Error state
* @param None
* @retval None
*/
void MyTKeys_ErrorStateProcess(void)
{
/* Add here your own processing when a sensor is in Error state */
}
/**
* @brief Executed when a sensor is in Off state
* @param None
* @retval None
*/
void MyTKeys_OffStateProcess(void)
{
/* Add here your own processing when a sensor is in Off state */
}
/**
* @brief Executed when a sensor is in Error state
* @param None
* @retval None
*/
void MyLinRots_ErrorStateProcess(void)
{
/* Add here your own processing when a sensor is in Error state */
}
/**
* @brief Executed when a sensor is in Off state
* @param None
* @retval None
*/
void MyLinRots_OffStateProcess(void)
{
/* Add here your own processing when a sensor is in Off state */
}
/**
* @brief This function handles a tick.
* @param None
* @retval None
*/
void User_Tick_Management(void) {
// tick counters set to zero first time this routine is called
static uint32_t tempo_50ms=0;
static uint32_t tempo_100ms=0;
static uint32_t tempo_200ms=0;
static uint32_t tempo_300ms=0;
static uint32_t tempo_400ms=0;
static uint32_t tempo_500ms=0;
// increment each counter, but bound to max count for each
tempo_50ms++;
tempo_100ms++;
tempo_200ms++;
tempo_300ms++;
tempo_400ms++;
tempo_500ms++;
tempo_50ms%=50;
tempo_100ms%=100;
tempo_200ms%=200;
tempo_300ms%=300;
tempo_400ms%=400;
tempo_500ms%=500;
// LINEAR_POSITION = MyLinRots[0].p_Data->Position
// above is a "scaled" position
// MyLinRots[0].p_Data->RawPosition
if (LINEAR_DETECT) {
// Now we just adjust when we are touching.
if (LINEAR_POSITION < 4) {
if (tempo_500ms==0) {
BSP_LED_Toggle(LED2);
}
} else if (LINEAR_POSITION < 8) {
if (tempo_300ms==0) {
BSP_LED_Toggle(LED2);
}
} else if (LINEAR_POSITION < 12) {
if (tempo_100ms==0) {
BSP_LED_Toggle(LED2);
}
} else { // pos >= 12
if (tempo_50ms==0) {
BSP_LED_Toggle(LED2);
}
}
}
}
/**
* @brief Display sensors information on LEDs and LCD
* @param status TSL user status
* @retval None
*/
void Process_Sensors(tsl_user_status_t status) {
/* LED1 is ON when TS1 on board is touched */
if (MyTKeys[0].p_Data->StateId == TSL_STATEID_DETECT){
BSP_LED_On(LED3);
} else {
BSP_LED_Off(LED3);
}
/* LED2 is ON when TS2 on board is touched */
if (MyTKeys[1].p_Data->StateId == TSL_STATEID_DETECT) {
BSP_LED_On(LED4);
} else {
BSP_LED_Off(LED4);
}
/* LED3 is ON when TS3 on board is touched */
if (MyTKeys[2].p_Data->StateId == TSL_STATEID_DETECT) {
BSP_LED_On(LED5);
} else {
BSP_LED_Off(LED5);
}
#ifdef isthisused
/* ECS information */
switch (status){
case TSL_USER_STATUS_OK_ECS_OFF:
BSP_LED_Off(LED5);
break;
case TSL_USER_STATUS_OK_ECS_ON:
BSP_LED_Toggle(LED5);
break;
default:
break;
}
#endif
if (LINEAR_DETECT) {
BSP_LED_On(LED1);
} else{
BSP_LED_Off(LED1);
}
}
感谢任何帮助。
事实证明,线性传感器需要单个 io 与传感器的每个组件的单个采样电容器配对。上面的问题是硬件设计为两组五个 io,带有两个采样电容器。一组的抽样上限为 3 ios,另一组的抽样上限为 2 ios.
我换了两个三通道组,每个通道组有一个io和一个sampling cap。之后代码运行良好。
// The three linrot channels
#define CHANNEL_0_IO_MSK (TSC_GROUP1_IO3)
#define CHANNEL_0_GRP_MSK (TSC_GROUP1)
#define CHANNEL_0_SRC (TSC_GROUP1_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_0_DEST (0) /* Index in destination result array */
#define CHANNEL_1_IO_MSK (TSC_GROUP2_IO4)
#define CHANNEL_1_GRP_MSK (TSC_GROUP2)
#define CHANNEL_1_SRC (TSC_GROUP2_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_1_DEST (1) /* Index in destination result array */
#define CHANNEL_2_IO_MSK (TSC_GROUP3_IO2)
#define CHANNEL_2_GRP_MSK (TSC_GROUP3)
#define CHANNEL_2_SRC (TSC_GROUP3_IDX) /* Index in source register (TSC->IOGXCR[]) */
#define CHANNEL_2_DEST (2) /* Index in destination result array */
我遇到过这种情况,我试图在软件而不是硬件上找到解决方案。此问题不是硬件问题,因为如果您尝试读取同一组和同一组中的通道,增量值将彼此相同。
我想,您在STMStudio中的读数如下:MyChannels_Data[3].Delta = MyChannels_Data[4].Delta
和MyChannels_Data[5].Delta = MyChannels_Data[6].Delta = MyChannels_Data[7].Delta
。
为了解决这个问题,您应该将您的 BANK_3 (LinRot Bank) 分开如下:
头文件:
// The linrot banks
// Channel 3 is a Group1_IO
#define BANK_3_NBCHANNELS (1)
#define BANK_3_MSK_CHANNELS (CHANNEL_3_IO_MSK | SHIELD_IO_MSK)
#define BANK_3_MSK_GROUPS (CHANNEL_3_GRP_MSK)
// Channel 4 is a Group1_IO, so I have to separate it from Bank 3, because Channel 3 is also a Group1_IO.
// Channel 5 is a Group2_IO, so I can combine it with Channel 4 in same Bank.
#define BANK_4_NBCHANNELS (2)
#define BANK_4_MSK_CHANNELS (CHANNEL_4_IO_MSK | CHANNEL_5_IO_MSK | SHIELD_IO_MSK)
#define BANK_4_MSK_GROUPS (CHANNEL_4_GRP_MSK | CHANNEL_5_GRP_MSK )
// Channel 6 is a Group2_IO, so I have to separate it from Bank 4 because Channel 5 is also a Group2_IO.
#define BANK_5_NBCHANNELS (1)
#define BANK_5_MSK_CHANNELS (CHANNEL_6_IO_MSK | SHIELD_IO_MSK)
#define BANK_5_MSK_GROUPS (CHANNEL_6_GRP_MSK)
// Channel 7 is a Group2_IO, so I have to separate it from Bank 6,
// because Channel 6 is also a Group2_IO.
#define BANK_6_NBCHANNELS (1)
#define BANK_6_MSK_CHANNELS (CHANNEL_7_IO_MSK | SHIELD_IO_MSK)
#define BANK_6_MSK_GROUPS (CHANNEL_7_GRP_MSK)
源文件:
/*============================================================================*/
/* Banks */
/*============================================================================*/
/* List (ROM) */
CONST TSL_Bank_T MyBanks[TSLPRM_TOTAL_BANKS] = {
// The three touchkey bankss
{&MyChannels_Src[0], &MyChannels_Dest[0], MyChannels_Data, BANK_0_NBCHANNELS, BANK_0_MSK_CHANNELS, BANK_0_MSK_GROUPS},
{&MyChannels_Src[1], &MyChannels_Dest[1], MyChannels_Data, BANK_1_NBCHANNELS, BANK_1_MSK_CHANNELS, BANK_1_MSK_GROUPS},
{&MyChannels_Src[2], &MyChannels_Dest[2], MyChannels_Data, BANK_2_NBCHANNELS, BANK_2_MSK_CHANNELS, BANK_2_MSK_GROUPS},
// The one linrot bank
{&MyChannels_Src[3], &MyChannels_Dest[3], MyChannels_Data, BANK_3_NBCHANNELS, BANK_3_MSK_CHANNELS, BANK_3_MSK_GROUPS},
{&MyChannels_Src[4], &MyChannels_Dest[4], MyChannels_Data, BANK_4_NBCHANNELS, BANK_4_MSK_CHANNELS, BANK_4_MSK_GROUPS},
{&MyChannels_Src[6], &MyChannels_Dest[6], MyChannels_Data, BANK_5_NBCHANNELS, BANK_5_MSK_CHANNELS, BANK_5_MSK_GROUPS},
{&MyChannels_Src[7], &MyChannels_Dest[7], MyChannels_Data, BANK_6_NBCHANNELS, BANK_6_MSK_CHANNELS, BANK_6_MSK_GROUPS},
};
配置文件:
#define TSLPRM_TOTAL_BANKS (7)
注意:图书馆的银行数量有限制。在我的例子中,我的申请中要求的银行数量超过了限制,然后我只是改变了这个值,我没有遇到任何问题。
回答有点晚了。但我希望它能有所帮助。
编辑:我在"UM1606 - STMTouch driver user manual"文档第122页找到了银行定义的提示,解释如下:
For optimum sensitivity and position reporting, all the channels composing a linear or a rotary touch sensor must be acquired simultaneously. This means that all the channels must belong to the same bank.
Note:The library allows to define a linear or a rotary touch sensor with channels belonging to different banks. A such configuration induces a loss of sensitivity and a higher noise level. Moreover, depending on the acquisition time, it is also possible to observe a position change when removing the finger from the sensor.
For optimum performance of a linear or rotary sensor, all channels of such a sensor must be acquired simultaneously.Therefore all channels must belong to the same bank, which means the I/Os must be selected from different analog I/O groups. Please refer to datasheet for more information regarding I/O groups and available capacitive sensing GPIOs.
总结:如果同一组I/Os不能在同一组中,如果传感器的所有通道都应在同一组中,则传感器的所有通道应属于不同的组。假设传感器是一个 6 通道线性传感器,那么通道可以连接如下:1-Ch = Group1_IO1,2-Ch = Group2_IO1,3-Ch = Group3_IO1, 4-Ch = Group4_IO1、5-Ch = Group5_IO1、6-Ch = Group6_IO1。因此,我们可以很容易地说硬件方案是更好的方案。但不要忘记软件解决方案也存在。但是,它没有那么敏感。