起因
会拿这个冷门板子开发的起因源自于好友的一个请求,帮助他去英国留学的对象完成一个课程设计作业。虽然料到会有一定难度,但没想到居然是卡在如何抢救一个变砖的板子上😤,代码部分倒是一帆风顺。
项目相关资料
下面是英国老师提供的几份资料,可供大家查阅。
购置开发板及相关资源
FRDM-KL46Z 面向Kinetis MKL46Z256VLL4 KL3 MCU Freedom开发平台
在淘宝上找到了卖这个板子的商家,可以说国内基本没有这个板子的货源,仅有的几家这个板子也非常贵,居然要350大洋,太夸张了,难道是板子上的硬件资源有什么特别的嘛,当时的我并没有多想,毕竟不是我付板子的钱(bushi😂),这里是一个巨大的伏笔,折磨了我2天。
接下来自然是购置杜邦彩色排线和矩阵键盘模块啦,鉴于这种资源淘宝就非常多了,就不放链接了。
其次由于当时暂时还住在自己家里,大量工具都在学校,家里并没有准备焊枪、焊锡等常用工具,只能等好友去买点基础装备过来了。
冻手冻手,我都说了冻手啊!
- 安装并配置Mbed Studio
- 下载并安装Mbed-OS C++类库
- 准备引脚配置文档并理解引脚功能
- 准备SLCD库文件并理解如何使用接口
- 准备Keybad库文件并理解如何使用接口,准备并查阅备用Keypad文档
- 下载DAPLink驱动以准备连接飞思卡尔板子
- BOOM!!!你得到了一块已经完美变砖的飞思卡尔板子
发生甚么事了?
在解释原因之前请允许我先聊下我自己的故事,在当时我下载完驱动并第一次接上板子时,一切都那么的正常,正常的绿灯闪烁,正常的预烧录程序执行,唯一的问题就是连接不上Mbed Studio,我以为是连接不稳定?于是我进行了一次插拔,这下乐了,板子完全不亮灯,此时,我还没意识到问题的严重性。也许是板子的boot程序问题?(对了但不完全对)我到飞思卡尔官网查阅文档后下载了最新的boot程序,害,多半是国内这种板子货源少,厂家没更新bootloader,多大点事。结果这就是噩梦的开始,无论我按照操作手册安装多少次固件,板子永远在一次插拔后变砖块。由于国内几乎没有学校用这块板子教学,更没有丰富的社区资源,我一开始完全找不到相关问题解决方案。实话说,花了2个晚上寻求解决方案无果后,我都打算和好友说可能板子有问题打算放弃了。
直到第二天我再次尝试去国外论坛寻求答案时才找到一些眉目,这里有一篇遇到非常类似更新飞思卡尔板子固件的博客文章。顺着这个线索,我完整的下载了OpenSDA_Bootloader,P&E drivers,MSD Debug等一系列驱动(什么报菜名?😂),但由于资料年代久远,我按照要求尝试多次仍然未能抢救这块砖头。又是半天的国外全网搜索,终于明白,我的电脑windows版本过高了,想要安全更新固件,必须降级windows版本至win7,我真是chao了微软の🐎了。
需要windows7好说,装个虚拟机很快就完事了,果然在win7下安装以上固件完全没问题,等更新固件完成后再次连接win10平台的Mbed Studio就能正常识别了,DAPLink本身也没任何问题,很好,也就浪费了我2天半时间,nmmd🫠。
等待好友帮忙完成焊接
板子能正常连接后,我们一起焊接完键盘,杜邦线等外设。只能说我们两个的焊接技术纯纯依托,勉强能保证两块东西连在一起罢了,我严重怀疑之后的键盘大量出现抖动、失灵问题和我们粗暴的焊接技术有关😂。只能说我确实用不来松香+焊锡这玩意,要么太多变成一个球,要么太少焊不住,焊枪头tm的又贼粗,完全在和泥吧啊喂。
正式开始编程
这部分当然是全部交给我了(不然找你干嘛🥲),其实也没有花太多时间,第一版代码也就爆肝到凌晨4点而已,主要是我个人一旦进入心流状态,很难停的下来,根本睡不着。而且这个状态效率也高,说实话强行断了非常可惜。至于后续的第二版第三版代码也是每次做一些功能上的调整,自然就没那么辛苦了。
起步最关键的当然是定义外设资源:
//定义外设
DigitalOut greenLED(LED1); // LED灯-绿
DigitalOut redLED(LED2); // LED灯-红
SLCD sLCD; //SLCD屏幕
TSISensor tsi; //触摸板
InterruptIn button1(SW1); //开关SW1
InterruptIn button3(SW3); //开关SW2
//Keypad mykey(PTD3, PTA2, PTA1, PTC8, PTA5, PTA4, PTA12); //老师设置的默认端口
Keypad mykey(PTD3, PTA1, PTA4, PTA2, PTC8, PTA5, PTA12); //键盘端口设置
FlashIAP fd;
简单列下主函数逻辑,至于每个功能函数实现细节就不列出来了,太长了,基本只涉及简单的逻辑:
/** 主函数
@note 这个键盘稀碎,记得输密码的时候一个一个键按,慢点来,不然可能出错
*/
int main()
{
yellowLED = !yellowLED;
redLED = !redLED;
fd.init();
flash_password_init();
while (true)
{
char* password = (char *)calloc((MAX_PASSWORD_LENTH+1),sizeof(char)); //Allocate memory for the input password string and initialize all of it to 0
if(button1.read()==1) //When switch 1 is not pressed, open the door procedure
{
password=get_password_hardware(password);
check_password_hardware(password);
}
else //Press switch 1 to enter password change mode, and the yellow light is on
{
flip_yellowled();
password=get_password_hardware(password);
change_password_hardware(password);
flip_yellowled();
}
free(password); //Free memory
thread_sleep_for(WAIT_TIME_MS);
}
}
这里为了程序结构更加美观(其实是他们老师要求),写了个自己的辅助功能库,myutils.cpp:
/** 显示滚动信息
@param message 输入想要显示的信息文本,最长60个字符
@param scrool_speed 单位ms,即每多少ms滚动一个字符
@param sLCD 外设对象,取对象地址
@note 最多显示60个字符
*/
void scroll_message(char message[60],int scroll_speed,SLCD &sLCD);
/** LED闪烁
@param led led外设
@todo 暂时不能用!
*/
void LEDflip(DigitalOut &led);
/** 等待密码期间让屏幕闪烁
@param sLCD 外设对象
@note 以 0.0.0.0 闪烁
*/
void waiting_password(bool mode,SLCD &sLCD);
/** 比对两个字符串
@param str1 字符串1指针
@param str2 字符串2指针
@return 返回两个字符串大小区别,0表示字符串相同,1表示str1长于str2
@note 不要输入空字符串
*/
int mystrcmp(const char *str1,const char *str2);
/** 复制字符串
@param strDest 目标字符串数组指针
@param strSrc 复制原字符串数组指针
@return 返回指向目标字符串数组的指针
@note 不要输入空字符串,返回的是指针
*/
char* mystrcpy(char *strDest, const char* strSrc);
这里面的函数其实都非常简单,唯一值得说道的就是如何在SLCD上显示滚动消息,再书写前需要做一下简单的计算:
void scroll_message(char message[60],int scroll_speed,SLCD &sLCD)
{
for (int start = 0; start < strlen(message)-3; start++) //-4 -> -3
{
for (int digit = 0; digit < 4; digit++)
sLCD.putc(message[start + digit]);
thread_sleep_for(scroll_speed);
}
}
main函数中也有一个函数实现时候需要仔细思考下,即如何在只能显示4位数字的SLCD上用户能够录入超过4位数字的密码?当屏幕上已经显示4位数字后,每输入一个数字要让前面的数字往左边推进一位,才能让用户正常看到自己键入的新数字。依旧在书写前可能需要实现做些计算,想清楚边界是多少:
/** get password
@param password input password(pionter)
@return 返回char*指针,指向用户输入的密码
@note Press the # key to finish typing
*/
char* get_password_hardware(char* password)
{
char key;
char POUND[] = "#";
int count=0;
bool wait=true;
waiting_password(wait,sLCD);
while (count<MAX_PASSWORD_LENTH)
{
if (mykey.KeyReady())
{
if(wait)
{
wait=false;
waiting_password(wait,sLCD);
}
key = mykey.ReadKey();
if (key == POUND[0])
{
if(count<4)
{
sLCD.Home();
return 0;
}
else
{
sLCD.Home();
return password;
}
}
else
{
*(password+count)=key;
if(count<4)
{
sLCD.putc(key);
}
else //Ensure that the last four digits are input
{
for (int start = 0; start < (count + 1) - 4; start++)
{
for (int digit = 0; digit < 4; digit++)
sLCD.putc(*(password+start + digit + 1));
}
}
count++;
}
}
}
sLCD.Home();
return 0;
}
大部分需要自己敲得代码已经放出来了,其他需要引用的外设库文件已经放在文章开头就不赘述了。
题外话
写完代码实现完功能,当然就是交给我好友对象让她理解再做些修改啦,后续主要也是卡在如何录入密码的逻辑那,我还专门画图讲了下如何算出的边界。。。很可惜没有让她理解🫠。不过倒也不重要,据我所知,咸鱼上做这种毕设项目能有3k的收入,好友惨痛被骗3k后时间来不及了才来找到我,结果几天就给他做完了😂。当然好友送了一大袋薯片和一大箱果汁,非常NICE!(吃到上火嘴巴起泡)苹果汁真的好好喝啊!!!🤤
不过实话说,再看自己的代码还是纯纯三脚猫,当时第一版Debug就耗了大量时间才搞到凌晨,只能说还需努力!
Comments NOTHING