1200|5

504

帖子

0

TA的资源

纯净的硅(初级)

楼主
 

【复旦微车规MCU FM33FT0A 系列】--TSI触摸 [复制链接]

本帖最后由 dirty 于 2024-2-22 09:38 编辑

        开发板FM33FT056A MCU集成了触摸检测功能,官方提供了完整TSI触摸解决方案,且有防液体误触、抑制电磁干扰、支持覆盖触摸、自动调优算法等优势特点。通过软硬件协同,可应用在汽车电子触摸领域,如车窗、车灯、中控面板等的触控应用。本篇讲述实现TSI按键触摸和滑条触摸及位置功能。

一.硬件原理

        开发板板载两个触摸按键BT0、BT1 和一个触摸滑条SLDER,原理图及硬件部分如下

图1:触摸按键与滑条

        TSI 模块使用自电容的方法来检测触摸行为。复旦微在TSI方面有齐全资料介绍,其集成了自有算法及配备调试工具TSITuner,一方面节约了成本,另一方面在方案应用上完整闭环,这一块做的挺不错。

 

二.代码准备

        官方提供了TSIDemo,这里做些解读与完善修改及应用。

1.关于TSI软件库介绍

(1). tsi.c, tsi.h:包含库的运行控制函数(启动、停止等);
(2). tsi_baseline.c, tsi_baseline.h: 包含基准线算法相关实现;
(3). tsi_calibration.c, tsi_calibration.h: 包含触摸硬件参数自动校准算法的相关实现;
(4). tsi_conf.h:用户配置文件, TSI 软件库的一些可配参数都罗列于此。我们仅提供对应该文件的模板 tsi_conf_template.h, 用户修改后重新命名为 tsi_conf.h 即可使用;
(5). tsi_def.h: 包含库所需的一些定义,包括一些配置可选参数值的定义;
(6). tsi_filter.c, tsi_filter.h: 包含 RawCount 滤波器的实现;
(7). tsi_interrupt.c: 包含 TSI 模块的中断服务程序;
(8). tsi_objects.c, tsi_objects.h: tsi_objects.c 包含全部的 TSI 模块控件定义和参数(触摸引脚TSI_Pins及通道TSI_ChannelSensorMap等),tsi_objects.h 包含全部 TSI 软件库数据结构定义; tsi_objects.c 我们仅提供对应的模板 tsi_objects_template.c, 用户修改后重新命名为 tsi_objects.h 即可使用;
(9). tsi_sensor.c, tsi_sensor.h:包含传感器使用的配置、初始化、更新状态函数;
(10). tsi_widget.c, tsi_widget.h:包含控件使用的配置、初始化、更新状态函数;

2.代码修改

(1)main函数去除TSI_DEBUG_xxx,添加前面已讲述调试串口打印,并添加按键、滑条触摸及位置检测,代码如下

int main(void)
{
    /* 使能IWDT */
    IWDT_Init(FL_IWDT_PERIOD_4000MS);

    /* Init FL driver library */
    FL_Init();

    /* 使能SVD, 阈�?.157V(falling)~4.257V(rising) */
    SVD_Init(SVD_MONTIOR_VDD, FL_SVD_WARNING_THRESHOLD_GROUP11, FL_SVD_REFERENCE_1P0V);
    /* 确认SVD监测结果是否高于阈值,如否则持续等�?*/
    while(false == SVD_Result_Confirmed(SVD_HIGHER_THRESHOLD, 2000U/*us*/));
    
    /* 使能BOR */
    RMU_BOR_Init(FL_RMU_BOR_THRESHOLD_2P00V);
   
    /* Init system clock */
    SystemClockInit();

    /* USER CODES AREA 1 BEGIN */

    /* USER CODES AREA 1 END */
    
    MF_Config_Init();
     
     
    /* Init TSI */
    TSI_Init();
    printf("TSI Init \r\n");
    
    /* Enable all widgets */
    TSI_Widget_EnableAll();

    /* Feed watchdog */
    FL_IWDT_ReloadCounter(IWDT);

    /* Start TSI */
    TSI_Start();
    printf("TSI Start \r\n");
    
    /* Feed watchdog */
    FL_IWDT_ReloadCounter(IWDT);
    
    /* Init and start TSI debug */
//    TSI_Debug_Init();
//    TSI_Debug_Start();

    /* USER CODES AREA 2 BEGIN */

    /* USER CODES AREA 2 END */

    while(1)
    {   
        /* USER CODES AREA 3 BEGIN */

        /* USER CODES AREA 3 END */

        /* Feed watchdog */
        FL_IWDT_ReloadCounter(IWDT);

        /* 电源掉电监测处理 */
        PowerDownMonitoring();

        /* Handle debug event */
        TSI_Debug_Handler();

        /* USER CODES AREA 4 BEGIN */

        /* USER CODES AREA 4 END */
              
        /* Wait until a scan sequence has completed */
        if(TSI_GETSTAT_SCAN_CPLT())
        {   
			
            TSI_CLRSTAT_SCAN_CPLT();
            
            /* Update all widgets */
            TSI_Widget_UpdateAll();

			if(TSI_WidgetList.bt0.buttonStatus==1)
			{
				printf("bt0 is touched\r\n");
			}

			if(TSI_WidgetList.bt1.buttonStatus==1)
			{
				printf("bt1 is touched\r\n");
			}
              
            
			if(TSI_WidgetList.slider.sliderStatus==1)
			{
				printf("silder is touched,position:%d--[range:0-255]\n",TSI_WidgetList.slider.centerPos);
			}

            
            /* Update debug interface trace buffer */
//            TSI_Debug_UpdateTrace();

            /* USER CODES AREA 5 BEGIN */

            /* USER CODES AREA 5 END */
        }

        /* USER CODES AREA 6 BEGIN */

        /* USER CODES AREA 6 END */
    }
}

 

(2)调试仿真时发现滑条触发状态没有置位,官方代码有点bug.修改TSI_Widget_UpdateSlider,添加sliderWidget->sliderStatus=sliderWidget->base.status;完整函数如下:

void TSI_Widget_UpdateSlider(TSI_SliderWidgetTypeDef* sliderWidget)
{
    if(sliderWidget->base.status == 1U)
    {
        int i;
        uint8_t peakIndex = 0U;
        uint16_t peakSignalVal = 0U;
        uint16_t centroidCalcData[3];
        uint16_t threshold = sliderWidget->base.activeTh - sliderWidget->base.activeHys;
        int32_t centroid;
        const TSI_MetaWidgetTypeDef *metaWidget = sliderWidget->base.meta;
        TSI_SensorTypeDef* sensor = metaWidget->sensors;
        int32_t mul = (TSI_SLIDER_RESOLUTION / (metaWidget->sensorCnt - 1)) << 8U;

        /* 
            Calculate the slider postion using centroid algorithm:
            1. Find the sensor X with the highest signal, which is the center of the touched area;
            2. Calcuate centroid using X's neighbour sensor;
        */
        
        /* Find peak value and corresponding sensor */
        for (i = 0; i < metaWidget->sensorCnt; i++)
        {
            if(sensor->diffCount > threshold && sensor->diffCount > peakSignalVal) 
            {
                peakIndex = i+1;
                peakSignalVal = sensor->diffCount;
            }
            sensor++;
        }
        
        if(peakIndex != 0)
        {
            /* Get neighbour sensors signal value */
            sensor = metaWidget->sensors;
            if(peakIndex == 1)
            {
                centroidCalcData[0] = 0;
                centroidCalcData[1] = peakSignalVal;
                centroidCalcData[2] = (int32_t)sensor[1].diffCount;
            }
            else if(peakIndex == metaWidget->sensorCnt)
            {
                centroidCalcData[0] = sensor[peakIndex-2].diffCount;
                centroidCalcData[1] = peakSignalVal;
                centroidCalcData[2] = 0;
            }
            else
            {
                centroidCalcData[0] = sensor[peakIndex-2].diffCount;
                centroidCalcData[1] = peakSignalVal;
                centroidCalcData[2] = sensor[peakIndex].diffCount;
            }
            
            /* Calculate centroid */
            centroid = ((int32_t)centroidCalcData[2] 
                        - (int32_t)centroidCalcData[0]) * mul / 
                        ((int32_t)centroidCalcData[0]
                        + (int32_t)centroidCalcData[1]
                        + (int32_t)centroidCalcData[2]);
            centroid += (peakIndex-1) * mul;
            centroid >>= 8U;
            sliderWidget->centerPos = centroid;
			
			
        }
    }
	//fix bug:sliderStatus not setted when touched or released
	sliderWidget->sliderStatus=sliderWidget->base.status;
	
}

        代码准备完毕,编译烧录。

三.测试

        打开串口,触摸BT0,BT1可看到触摸按键被触发;滑条位置从右至左(USB TYPE-C朝左)位置为0-255,可点触或者滑动触摸。完整日志如下

图2:触摸日志
       

         至此,触摸功能得以应用实现,效果不错,触摸灵敏且滑条位置准确。

 

此帖出自汽车电子论坛

最新回复

3mm倒还是可以的。间隔挺远。   详情 回复 发表于 2024-2-27 09:09
点赞 关注
个人签名

保持热爱


回复
举报

7193

帖子

2

TA的资源

版主

沙发
 
这种电容传感器可以中间隔玻璃之类的吗?
此帖出自汽车电子论坛

点评

可以的  详情 回复 发表于 2024-2-22 21:05
 
 

回复

504

帖子

0

TA的资源

纯净的硅(初级)

板凳
 
wangerxian 发表于 2024-2-22 19:40 这种电容传感器可以中间隔玻璃之类的吗?

可以的

此帖出自汽车电子论坛

点评

那可以隔多厚检测?  详情 回复 发表于 2024-2-23 09:12
个人签名

保持热爱

 
 
 

回复

7193

帖子

2

TA的资源

版主

4
 

那可以隔多厚检测?

此帖出自汽车电子论坛

点评

有在3mm左右厚度的亚克力板上测过可以  详情 回复 发表于 2024-2-26 23:29
 
 
 

回复

504

帖子

0

TA的资源

纯净的硅(初级)

5
 
wangerxian 发表于 2024-2-23 09:12 那可以隔多厚检测?

有在3mm左右厚度的亚克力板上测过可以

此帖出自汽车电子论坛

点评

3mm倒还是可以的。间隔挺远。  详情 回复 发表于 2024-2-27 09:09
个人签名

保持热爱

 
 
 

回复

7193

帖子

2

TA的资源

版主

6
 
dirty 发表于 2024-2-26 23:29 有在3mm左右厚度的亚克力板上测过可以

3mm倒还是可以的。间隔挺远。

此帖出自汽车电子论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表