开发背景: 在各高校,英语四、六级考试是典型的标准化考试形式,它同常规的考试相比流程相对要复杂些。一般情况下,如果不是被轮到很少有人愿意去监这种考试。此次就借LPC54114 Lite 开发板来解决这个问题,以自动在指定的时段给出任务提示并执行一些控制操作。 设计思路: 借助LPC54114内部的RTC通过时间基准,并在指定的多个时段向3类对象给出不同的提示信息或控制信号。 这3类对象分别是监考人员、考生及屏蔽器,监考人员的主要任务是控制考试进程、收发试卷和答题卡、填写开场记录等;考生则按考场要求按进程完成考试;屏蔽器则除测试听力外,将一直处于开通状态,以屏蔽外部的电子信号进入。 为此,以TFT屏为监考人员显示提示信息;用语言模块和音箱来向考生发送不同时段的语音提示,以降低若采用显示器件所造成的产本提升;采用继电器则可以自动控制屏蔽器的开关。 由于RTC在断电时,会停止计时,为此时常要设置RTC的初始时间。为了避免不必要的键入操作,特采用串行通讯的方法,通过辅助软件来巧用计算机系统的时间值来设置RTC初始值。 整体构成: 为达到设计功能,其整体构成如图1所示。 图1 系统构成图
图2 实物图
在双核结构下,该装置的处理流程如图3所示。 图3 处理流程图
技术实现: 该设计涉及:双核方式运行、核间通讯、核间数据共享、RTC、温度检测、数字语音录制、flash语音存储、I2S语音播放、TFT屏显示、LED进程指示、继电器控制、串行通讯等。 1.核间通讯 进程传送程序: - // M4:
- uint8_t JC;
- void MAILBOX_IRQHandler() // M4
- {
- g_msg = MAILBOX_GetValue(MAILBOX, kMAILBOX_CM4);
- MAILBOX_ClearValueBits(MAILBOX, kMAILBOX_CM4, 0xffffffff);
- }
- // Initialize Mailbox
- MAILBOX_Init(MAILBOX);
- // Enable mailbox interrupt
- NVIC_EnableIRQ(MAILBOX_IRQn);
- JC=i;
- MAILBOX_SetValue(MAILBOX, kMAILBOX_CM0Plus,i);
- LED进程指示程序:
- //M0+:
- uint8_t JCH;
- void MAILBOX_IRQHandler() //M0+
- {
- JCH = MAILBOX_GetValue(MAILBOX,kMAILBOX_CM0Plus); //kMAILBOX_CM4
- //PRINTF(" *time* %02d\r\n",g_msg);
- MAILBOX_ClearValueBits(MAILBOX, kMAILBOX_CM0Plus, 0xffffffff);
- if(JCH==1) GPIO_SetPinsOutput(GPIO, 0, 1u << 15);
- if(JCH==2) GPIO_SetPinsOutput(GPIO, 0, 1u << 19);
- if(JCH==3) GPIO_SetPinsOutput(GPIO, 0, 1u << 21);
- if(JCH==4) GPIO_SetPinsOutput(GPIO, 0, 1u << 22);
- if(JCH==5)GPIO_ClearPinsOutput(GPIO, 0, 1u << 25);
- if(JCH==6)GPIO_ClearPinsOutput(GPIO, 0, 1u << 26);
- if(JCH==7)GPIO_ClearPinsOutput(GPIO, 0, 1u << 29);
- //if(JCH==8)GPIO_ClearPinsOutput(GPIO, 0, 1u << 30);
- }
复制代码2.RTC计时 在该设计中,RTC计时是整个系统的进程管控核心,实现RTC计时与显示功能的程序如下: - while(len<7);//等待RTC初始值的读取
- rtc_datetime_t date;
- RTC_Init(RTC);
- //设置RTC初始值
- date.year = 2017;
- date.month = 07;
- date.day = 27;
- date.hour = (bufferString[0]-'0')*10+bufferString[1]-'0';
- date.minute = (bufferString[3]-'0')*10+bufferString[4]-'0';
- date.second = (bufferString[6]-'0')*10+bufferString[7]-'0';
- RTC_StopTimer(RTC);
- RTC_SetDatetime(RTC, &date);
- RTC_StartTimer(RTC);
- RTC_GetDatetime(RTC, &date);
- //PRINTF("Current date: %04d-%02d-%02d\r\n",date.year,date.month,date.day);
- //PRINTF("Current time: %02d:%02d:%02d\r\n",date.hour,date.minute,date.second);
- LCD_ShowNum(20,100,date.hour,2,16);
- LCD_ShowChar(36,100,':',16,0);
- LCD_ShowNum(44,100,date.minute,2,16);
- LCD_ShowChar(60,100,':',16,0);
- LCD_ShowNum(68,100,date.second,2,16);
- //实现RTC计时值/
- secondp=date.second;
- i=0;
- LCD_ShowNum(200,100,i,1,16);
- while(1)
- {
- RTC_GetDatetime(RTC, &date);
- if(secondp != date.second)
- {
- //PRINTF("Current time: %02d:%02d:%02d\r\n",date.hour,date.minute,date.second);
- secondp=date.second;
- if((t[i]==date.hour)&&(p[i]==date.minute)&&(0==date.second))
- {
- //PRINTF(" *time*: %02d:%02d:%02d\r\n",date.hour,date.minute,date.second);
- LCD_ShowChar(200,120+i*30,'*',16,0);
- i++;
- LCD_ShowNum(200,100,i,1,16);
- MAILBOX_SetValue(MAILBOX, kMAILBOX_CM0Plus,i);
- if(i==7)
- {
- i=0;
- for(j=0;j<6;j++)
- {
- LCD_ShowChar(200,120+j*30,' ',16,0);
- }
- }
- }
- LCD_ShowNum(20,100,date.hour,2,16);
- LCD_ShowNum(44,100,date.minute,2,16);
- LCD_ShowNum(68,100,date.second,2,16);
- }
- }
复制代码
图4 RTC计时验证
3.温度检测 (在需要的情况下,通过添加光隔继电器来控制电扇、空调的温度调节设备。) 通过添加以下2个函数即可进行温度的检测。 uint8_t pct2075_i2c_init(void) uint8_t pct2075_i2c_read(float *data) 具体的温度读取过程由以下程序实现: - pct2075_i2c_init();
- while(1)
- {
- pct2075_i2c_read((float *)&fPCTValue);
- if(fPCTValue>=0)
- {
- n=(int)(fPCTValue*100)/100;
- M0_TO_M4_T=(int)(fPCTValue*100)/100;
- if(n!=M0_TO_M4_T)
- {
- //只传送零度之上的温度供显示
- PRINTF("Temperature Value is +%d.%d oC.\r", (int)(fPCTValue*100)/100, (int)(fPCTValue*100)%100);
- M0_TO_M4_T=(int)(fPCTValue*100)/100;
- }
- }
- else
- PRINTF("Temperature Value is -%d.%d oC.\r", (int)((0-fPCTValue)*100)/100, (int)((0-fPCTValue)*100)%100);
- delay();
- }
复制代码实现温度值的显示的语句如下: LCD_ShowNum(120,100,M0_TO_M4_R,2,16); LCD_ShowChar(138,100,'C',16,0); 4.TFT屏显示 在该设计中,为了更多地显示信息特采用TFT屏来完成显示任务,并选取串口屏以节省GPIO资源。TFT屏与LPC54114开发板的引脚连接关系: SCE --P0.11 RST --P0.13 DC --P0.12 DIN --P0.14 SCLK--P1.8 LED+--P1.9 界面显示函数如下: - void xianshi(void)
- { uint8_t i;
- LCD_Clear(RED);
- BACK_COLOR=RED;
- POINT_COLOR=WHITE;
- //32*32 标准化考试进程调试器
- showhanzi32(20,20,0);
- showhanzi32(60,20,1);
- showhanzi32(100,20,2);
- showhanzi32(140,20,3);
- showhanzi32(180,20,4);
- showhanzi32(20,60,5);
- showhanzi32(60,60,6);
- showhanzi32(100,60,9);
- showhanzi32(140,60,10);
- showhanzi32(180,60,11);
- showhanzi16(120,120,0); //入场
- showhanzi16(140,120,1);
- showhanzi16(120,150,2); //开考
- showhanzi16(140,150,3);
- showhanzi16(120,180,4); //写作
- showhanzi16(140,180,5);
- showhanzi16(120,210,6); //听力
- showhanzi16(140,210,7);
- showhanzi16(120,240,8); //答题
- showhanzi16(140,240,9);
- showhanzi16(120,270,10); //结束
- showhanzi16(140,270,11);
- LCD_ShowString(20,120,120,16,16,"8:00-9:00 "); //1
- LCD_ShowString(20,150,120,16,16,"9:00-9:10 "); //2
- LCD_ShowString(20,180,120,16,16,"9:10-9:40 "); //3
- LCD_ShowString(20,210,140,16,16,"9:40-10:10 "); //4
- LCD_ShowString(20,240,140,16,16,"10:10-11:20 "); //5
- LCD_ShowString(20,270,140,16,16,"11:20-11:30 "); //6
- }
复制代码
图5 TFT显示界面
5.串行通讯 借助串行通讯功能可从外部来接收必要的数据信息,在该设计中是通过串行通讯来接收RTC的初始时间值,具体的使用方法如下。 uint8_t bufferString[8] = {0}; uint8_t len=0; 串行通讯中断接收函数如下: - void FLEXCOMM0_IRQHandler(void)
- {
- char ch=0;
- if ((kUSART_RxFifoNotEmptyFlag | kUSART_RxError) & USART_GetStatusFlags(USART0))
- {
- ch = USART_ReadByte(USART0);
- bufferString[len]=ch;
- //PRINTF("\r\nM0 Receive from PC : %c\r\n", ch);
- if(len<7) len++;
- }
- }
复制代码6.I2S语音播放 为进行语音播放,是采用数字录音芯片事先进行语音录制并存在FLASH芯片中,在播放是再通过I2S芯片进行语音的再现。期间使用的关键函数有spiflash_init()、dmic_init()、pct2075_i2c_init()、wm8904_i2s_init()等。鉴于FLASH中存储的语音约16秒,故暂且播放一段语音信息。解决SD卡存储后再改为多时段语音播放。 受速度的影响,在进行语音再现是通过2个内存作为缓冲区来交替工作的,当一个在读取时,另一个在加速填充数据,以便连续播放不出现间断。 图6 以通讯方式接收RTC起始值
结语: 十分感谢论坛组织的这次活动及坛友所分享的经验,使自己从单核设计迈进了双核设计的门槛,并掌握了双核间的协作通讯问题,进而能将单核上实现的一些功能移植到双核上来实现该设计。限于时间和水平所,尽管整体上基本达到了设计的需要,但也仍存在尚需改进与完善之处,如实现多语音段录制与播放及以文件方式来管理语音库的播放等,期待对LPC5414的应用能跨上一个新的高度。
|