期末设计预期的效果是整个系统能对环境温度、环境的光照情况进行测量及显示,并且能对时间及日期进行显示。时间与日期的控制不再打算用按键进行修改,取而代之用蓝牙模块实现手机与蓝牙模块之间单向通信,即手机向蓝牙模块发送当前的时间或日期,蓝牙模块接受数据,通过内部代码对数据进行筛选与解析,最后更新芯片自身数据为手机发送的数据。
1、光敏传感器AO端口接GPIO_PA_0
2、热敏传感器AO端口接GPIO_PA_1
3、蓝牙模块端口RXD接GPIO_PA_9
4、蓝牙模块端口TXD接GPIO_PA_10
手机与芯片之间的单向通信首先要解决以下几个问题:
1、如何确保接收数据的完整性?
2、如何判断传输数据的合法性?
解答如下:
—— 2023/10/16
首先需要注意的就是数据之所以会出现丢失,主要原因在于手机向接受端发送信息时,接收端不能及时接受信息,以至于前一个数据还未来的及接受就被后来的数据覆盖
数据不能被及时接收的原因:
网上常用数据接收代码:
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
Serial_RxData = USART_ReceiveData(USART1); //一个一个接收
Serial_RxFlag = 1;
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
由上述串口接收数据中断函数可以看出,触发中断后数据总是一个字节逐个被Serial_RxData
变量接收
接着标记标志位Serial_RxFlag
,主函数发现标志位变化,才会接受并储存Serial_RxData
上的数据
这个逻辑看似没有问题,但漏洞在于,我们的主函数不可能时刻判断标志位的值是否变化吧?朴素的说主函数不可能就执行判断标志位是否变化这一个语句吧?正是由于主函数在执行其他语句的时候导致没能时刻观察标志位的变化,而导致数据不能被立即接收,最终导致了数据丢失
那么解决方向就显而易见了,即如何做到数据能在中断发生的时候就立即接收呢?
答案就是数组
优化代码:
void USART1_IRQHandler(void)//中断函数
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
news[I] = USART_ReceiveData(USART1);//读数据
Serial_RxFlag = 1;//至标志位为有数据
I ++;
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
在中断产生的时候就立即用数组进行接收,同时标记标志位
主函数发现标志位变化了,等待一会就可以获取数组,取出传输方发送的全部信息了
传输方发送的信息不可能都是符合标准的,那么如何对数据进行筛选就显得及其重要
首先对我们需要的正确信息进行分析其特点:
例如需要获取的正确信息如下:
日期:2023/10/17
时间:21:57:55
分析上述两个典型数据,可以发现日期的特点是数据里存在/
,数据时间特点是有:
,那么第一次筛选条件就是判断接收数据是否存在上述任意一种符号。
这个在数据传输阶段就可以用两个标志位判断:
if(news[i] == '/') flagDate = 1;
if(news[i] == ':') flagTime = 1;
接下来摆在面前的就是假若筛选后的数据里出现超过两个/
或:
符号的时候
再进一步讲上若传入的数据符号为两个,但是传入的时间为25:15:80
阁下又应该如何应对?
要解决上述问题还是要对传入数据的特点进行细节分析:
拿日期 2023/10/17 进行分析,其中/
符号出现了两次我们完全可以用一个cnt
在拆解数据的过程中进行计数,若最后cnt
的大小不等于2的时候那么这个数据就会被判断为不合法这样符号问题就解决了
那么又如何对年份,月份,天数、进行判别呢?这就需要将数据进行切割了拿2023/10/17
示范,分析数据,巧妙的是在2023出现的时候cnt = 0
,也就是在2023
之前没有出现/
而到10
出现的时候cnt = 1
,最后17
出现的时候自然cnt = 2
。恍然大悟用一个updateDate[cnt]
分别对数据进行储存即可updateDate[0] = 2023、updateDate[1] = 10、updateDate[2] = 17
再对这三个数据分别分析就可以最终判断传入的数据是否合法了!
实现代码:
uint8_t Function_DateState(unsigned int *updateDate, char *News){
uint8_t cnt = 0;
uint8_t i = 0;
uint8_t end = Serial_GetI();
char month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
while(i < end){
if(News[i] == '/') {
cnt ++;
i ++;
if(cnt >= 3) {
return 0;
}
continue;
}
updateDate[cnt] = updateDate[cnt]* 10 + (News[i] - '0');
i ++;
}
if(cnt != 2) return 0;
if(Function_Numlength(updateDate[0]) >= 5 || updateDate[0] > 9999 || updateDate[0] == 0) return 0;
if((updateDate[0] % 4 == 0 && updateDate[0] % 100 != 0 )|| updateDate[0] % 400 == 0) month[2] = 29;
else month[2] = 28;
if(Function_Numlength(updateDate[1]) >= 3 || updateDate[1] > 12 || updateDate[1] == 0) return 0;
if(Function_Numlength(updateDate[2]) >= 3 || updateDate[2] > month[updateDate[1]]|| updateDate[2] == 0) return 0;
Time_GetArrayMonth()[2] = month[2];//这里年份也会发生变化,要修改原有数据
return 1;
}
—— 2023/10/17