辉芒微FT62FCC开发实战分享
以下为AI文章摘要本文分享了基于辉芒微FT62FCC芯片开发交流有刷电机产品的经验。重点介绍了五个功能模块的实现:1)使用VisualTouchTL软件配置触摸按键,包括按键状态获取和多按键处理;2)通过PORTA中断采集过零信号;3)根据过零信号控制可控硅;4)采用TIM2定时中断解码IR信号;5)数码管扫描显示驱动。文章详细说明了各模块的硬件连接和软件实现要点,特别强调了触摸按键调试中的整机与
毕业以来也算稍微有几年了,期间主要使用ARM架构的芯片进行开发或者对着无刷电机程序调参。类似辉芒微(FMD)这种芯片可以说是第一次使用,在这里将开发例程简单梳理总结一下,希望能帮到后续接触到的人。
当然,由于项目本身虽然简单但是同样涉密,所以此次分享不涉及原理图及具体完整代码的分享,还请各位看客多多谅解。
本次项目为基于FT62FCC的触摸按键检测芯片进行一款交流有刷电机产品的实现,具体芯片型号虽与FT62FCC略有不同但从使用上基本一致。在硬件实现上,具体的I/O使用如下表所示。
| 输出(0)/输入(1) | 功能 | ||
| 1 | PA0 | 0 | COM1 |
| 2 | PA1 | 1 | OSC1 |
| 3 | PA2 | 1 | OSC2 |
| 4 | PA3 | 0 | COM2 |
| 5 | PA4 | 1 | TIMER_Key3 |
| 6 | PA5 | 1 | IR_IN |
| 7 | PA6 | 1 | ON/OFF_Key1 |
| 8 | PA7 | 1 | GL |
| 9 | PD0 | 1 | SPEED_Key2 |
| 10 | PD1 | 0 | SEG_C |
| 11 | PB0 | 0 | SEG_D |
| 12 | PB1 | 0 | SEG_E |
| 13 | PB2 | 1 | Sleep_Key5 |
| 14 | PB3 | 1 | OSC_Key4 |
| 15 | PD4 | 0 | SEG_G |
| 16 | PB4 | 0 | SEG_F |
| 17 | PB5 | 0 | SEG_COM |
| 18 | PB6 | 0 | SEG_A |
| 19 | PB7 | 0 | SEG_B |
| 20 | PC0 | 0 | TRIAC_L |
| 21 | GND | ||
| 22 | PC1 | 0 | TRIAC_ML |
| 23 | PC2 | 0 | TRIAC_M |
| 24 | VDD | ||
| 25 | PC5 | 0 | TRIAC_OSC |
| 26 | PC6 | 0 | TRIAC_H |
| 27 | PD5 | 1 | C_Ref |
| 28 | PC7 | 0 | TRIAC_MH |
从引脚分配可以看出,I/O使用和功能实现主要分为五个方面:
- 触摸按键检测 - 通过FMD官方软件VisualTouchTL进行配置
- 过零信号采集 - 利用芯片PORTA的边沿中断功能实现
- 电机驱动 - 根据采集到的过零信号来控制可控硅
- IR信号接收 - 通过TIM2定时器中断检测IR端口电平变化实现解码
- 数码管与LED驱动 - 采用扫描方式实现多路LED共享驱动
一.触摸按键的调试
在项目的最初,我们需要对触摸按键电容的原理有所了解
基于该原理,我们可以知道触摸按键电容在具体的I/O端口上的变化并非简单的高低电平电平变化。在实际中,端口的变化为如下图所示(CH1黄线为触摸按键I/O信号)
此处我们可以借用FMD所提供的可视化软件进行配置。此处应当注意,若为中途接手或旧项目重新开发,应尽量使用与MCU出货日期相近版本的IDE和软件,否则可能出现ID校验失败导致烧录器无法烧录软件的情况。
下载安装并打开VisualTouchTL,具体的项目工程建立与使用可参考FMD官方视频
https://www.bilibili.com/video/BV1M84y1V7oj/?spm_id_from=333.1391.0.0&vd_source=e7de9cc04354bdc12789a3ad18ce1145
在成功选择芯片并建立工程后,我们根据需要对I/O进行配置得到如下界面。在当前界面中,由于触摸按键需求,CS和EMI为必选项。高灵敏为在源代码的基础上对滤波和采样进行了修改,后续可在代码文件touch.h中修改,可根据需求选择。低功耗为可选项,由于本次项目为AC供电项目,为开发便利,本次没有选择。
在这里,当我们配置完并调试按键状态为OK后,由于配置的先后顺序产生了Key1-Key5。此处的配置顺序尽量与开发者代码习惯相同,根据Key1-Key5的配置顺序后续对按键采集产生了回传数据0-5。
在生成代码后,通过代码我们可以知道
while(1)
{
//清看门狗
CLRWDT();
//按键扫描
TSC_Scan();
if(TSC_DataProcessing()== 1) //返回1表示所有按键处理完成一次,请和TSC_Scan一起使用,否则影响扫描速度。
{
strongest = TSC_GetCsKey();
single = TSC_GetLocalKey();
SleepProcess(); //睡眠处理函数需放置在if(TSC_DataProcessing()== 1)里面
}
}
其中,由于函数中存在滤波算法的,请注意确保按键采集模块执行为实时的。
函数TSC_GetLocalKey更新了当前按键状态,回传值从Key1到Keyx依次对应了bit0到bitx。例如,当按键空闲状态下,该函数回传值为0;若Key1按下,bit0为1,回传值为1;若Key1和Key2同时按下,bit0和bit1为1,回传值为3,以此类推。
最强按键状态可以通过TSC_GetCsKey来进行更新,该函数回传值即为当前最强按键值。其中,在空闲状态下,该函数回传值为0;若Key1为最强按键,则回传值为1。依次类推,我们可以得到目前的按键状态。此外,在此处应注意,若有多个按键同时触发,则TSC_GetCsKey回传值为0。
因此,在函数处理上,如果我们要求不考虑多按键同时触发时,在采集按键时需要同时对TSC_GetLocalKey进行判断。在代码上可以做如下处理。
void RealKeyNum (void)
{
//当且仅当按键空闲时更新按键
if(LastNum == 0)
{
RelNum = strongest;
LastNum = RelNum;
}
else
{
if(single == 0)
{
LastNum = single;
}
}
}
while(1)
{
//按键扫描
TSC_Scan();
if(TSC_DataProcessing()== 1) //返回1表示所有按键处理完成一次,请和TSC_Scan一起使用,否则影响扫描速度。
{
strongest = TSC_GetCsKey(); //更新最强按键状态
single = TSC_GetLocalKey(); //更新按键触发状态
//睡眠处理函数需放置在if(TSC_DataProcessing()== 1)里面,若无休眠功能,可屏蔽
SleepProcess();
RealKeyNum(); //此处最强按键保存在变量RelNum
}
//在这之后根据RelNum进行进一步处理
}
另外,考虑到实际项目,我们在进行采集的状态分为裸PCB触发和整机状态触发两种状态,通过使用VisualTouchTL分别测量两种状态的按键值。
以同为高灵敏度为例,经过对比我们可得在裸PCB触发和整机状态触发有如下不同:
在多数情况下,若触发不灵,在确保硬件无异常的情况下,仅稍微上调有效阈值(如KeyX_ON)并下调无效阈值(如KeyX_OFF)即可扩大触发阈值范围。放大倍数尽可能维持高倍数来确保整机触发无异常。
二.过零信号的处理
由于项目使用PA7来采集过零信号,所以我们只能通过PORTA中断来进行信号采集。
此处需要注意的是,PORTA中断为I/O电平变化中断,即I/O从0-1或1-0均可产生中断。在此基础上,又由于所有PORTA共用标志位PAIE和PAIF,所以如果需要使用复数PORTA中断,在中断产生时需根据需要对具体I/O的电平进行采集来判断具体是哪一个PORTA产生中断。
在此基础上,为避免PORTA中断的误触,当交流项目使用多个PORTA中断时,我们应当确保I/O信号的平稳。即在AC接入时,使用隔离探头确保每个PORTA引脚浮空状态下无剧烈电平变化。
//MCU中断函数
void interrupt ISR(void)
{
//PORTA电平变化产生中断
if(PAIE && PAIF)
{
ReadAPin = PORTA; //读取PORTA数据
PAIF = 0; //清PAIF标志位
PAIE = 0; //暂先禁止PA0中断
IOCA7 =0; //禁止PA0电平变化中断
GLflag = 1; //过零信号产生中断
}
}
//注意系统时钟、IO初始化中TRISA中PA7需要置1,WPUA中PAY置0
void PA7_Level_Change_INITIAL(void)
{
ANSEL0 &= ~0x80;
TRISA7 =1; //SET PA0 INPUT
ReadAPin = PORTA; //读取一下相应的端口寄存器
PAIF =0; //清PA INT中断标志位
IOCA7 =1; //使能PA7电平变化中断
PAIE =1; //使能PA INT中断
GIE =1; //使能全局中断
}
void main(void)
{
while(1)
{
//过零采集
PA7_Level_Change_INITIAL();
//根据过零信号进行进一步控制
}
}
三.可控硅控制
此处可讲的不多,根据过零信号"GLFLAG"来开关可控硅即可。注意实际控制中应当多次置高来确保信号的有效性,具体实现信号类似PWM波。
此处仅放几个实际波形图来示意。
蓝线C3为I/O波形,粉线C2为AC交流电压
蓝线C3为I/O波形,粉线C2为AC交流电压
四.IR信号驱动
在初始版本程序中,我尝试通过IR端口(PA5)的中断来启动TIM2定时器,利用定时器测量PA5引脚高低电平的持续时间以实现IR信号解码。但在实际测试中发现,当设备使用交流电源时,IR端口存在明显噪声干扰,导致无法准确测量PORTA的电平变化时间。因此最终改用TIM2定时中断的方式来实现IR信号解码。
使用隔离探头可以观测到IR端口存在明显的杂波
当然,在IR和GND之间添加一枚合适的电容是可以增加信号质量的
由于项目的IR信号并非标准通讯协议,所以此处的IR信号有关代码仅做示意使用
void interrupt ISR(void)
{
//定时器2的中断处理**********************
if(TMR2IE && TMR2IF) //100us中断一次 = 5KHz
{
TMR2IF = 0;
ir_decode_100us(); //IR数据采集 每100us判断一次IR电平
Re_Irnum(); //IR按键处理
}
}
//TIM1用作定时中断推进程序
//此处TIM2设置为每100us产生一次中断(16Mhz情况下)
void TIMER2_INITIAL (void)
{
T2CON0 = 0B00000001; //T2预分频1:4,后分频1:1
//BIT7: 0:无意义; 1:把PR2/P1xDTy缓冲值分别更新到PR2寄存器和P1xDTy_ACT
//BIT6~BIT3: 定时器2输出后分频比选择 0000:1:1;0001:1:2;……1:16
//BIT2:0:关闭定时器2;1:打开定时器2
//BIT1~0:定时器2预分频选择 00:1;01:4;1x:16
T2CON1 = 0B00000000; //T2时钟来自系统时钟,PWM1连续模式
//BIT4: PWM模式选择 0:连续模式;1:单脉冲模式
//BIT3: 0:PWM模式;1:蜂鸣器模式
//Timer2时钟源选择:000:指令时钟;001:系统时钟;010:HIRC的2倍频;100:HIRC;101:LIRC 110-LP 111-XT
TMR2H = 0; //定时器2计数寄存器,定时值=200*(4*2/16M)=200*0.5us=100us
TMR2L = 0;
PR2H = 0;
PR2L = 200; //TIMER2周期寄存器
TMR2IF = 0; //清TMER2中断标志
TMR2IE = 1; //使能TMER2的中断(配置成timer定时器时不注释)
TMR2ON = 1; //使能TMER2启动
PEIE = 1; //使能外设中断
GIE = 1; //使能全局中断
}
5.数码管与LED驱动
此处没有太多可以讲得,注意多COM驱动时需要先关闭多余COM的端口再进行驱动,否则用户体验上可能会看到残留灯光
以驱动数码管代码为例
// 数码管显示函数
void display_digit(uint num) {
// 关闭所有COM端 (共阴数码管)
COM1 = 1;
COM2 = 1;
COM3 = 1;
// 数字0-9的段码映射表 (1=点亮, 0=熄灭)
// 顺序: A,B,C,D,E,F,G
static const uint digit_map[10] = {
0b1111110, // 0: ABCDEF
0b0110000, // 1: BC
0b1101101, // 2: ABDEG
0b1111001, // 3: ABCDG
0b0110011, // 4: BCFG
0b1011011, // 5: ACDFG
0b1011111, // 6: ACDEFG
0b1110000, // 7: ABC
0b1111111, // 8: ABCDEFG
0b1111011 // 9: ABCDFG
};
// 验证输入范围 (0-9)
if(num > 9) return;
// 获取当前数字的段码
uint8_t seg_pattern = digit_map[num];
// 设置各段状态 (从高位到低位: A→B→C→D→E→F→G)
SEG_A = (seg_pattern & 0b1000000) ? 1 : 0;
SEG_B = (seg_pattern & 0b0100000) ? 1 : 0;
SEG_C = (seg_pattern & 0b0010000) ? 1 : 0;
SEG_D = (seg_pattern & 0b0001000) ? 1 : 0;
SEG_E = (seg_pattern & 0b0000100) ? 1 : 0;
SEG_F = (seg_pattern & 0b0000010) ? 1 : 0;
SEG_G = (seg_pattern & 0b0000001) ? 1 : 0;
// 开启当前COM端 (COM3控制目标数码管)
COM3 = 0;
}
以上便是基于辉茫微芯片FT62FCC的应用与解析。鉴于个人水平所限,文中若有任何疏漏或代码优化建议,诚邀各位读者批评指正。
更多推荐

所有评论(0)