seo怎样新建网站,汕头建总,网站流量优化,建设部网站 法规由手机向蓝牙模块传输时间信息#xff0c;Stm32获取信息并将已存在信息修改为传入信息
测试代码#xff1a;
#include stm32f10x.h // Device header
#include Delay.h
#include OLED.h
#include Serial.huint16_t num…由手机向蓝牙模块传输时间信息Stm32获取信息并将已存在信息修改为传入信息
测试代码
#include stm32f10x.h // Device header
#include Delay.h
#include OLED.h
#include Serial.huint16_t num 0;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
char News[100] ;
uint8_t flag 1;/*初始化通用定时器TIM2*/
void Timer_Init(void){RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//APB1外设开启TIM_InternalClockConfig(TIM2);//选择内部时钟/*初始化时基单元*/TIM_TimeBaseInitStructure.TIM_ClockDivision TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode TIM_CounterMode_Up;//向上计数TIM_TimeBaseInitStructure.TIM_Period 10000 - 1;//ARR自动重装TIM_TimeBaseInitStructure.TIM_Prescaler 7200 - 1;//psc预分频器TIM_TimeBaseInitStructure.TIM_RepetitionCounter 0;//高级计时器内容直接给零//记录1s TIM_TimeBaseInit(TIM2, TIM_TimeBaseInitStructure);//刚初始化完就会进中断TIM_ClearFlag(TIM2, TIM_FLAG_Update);//消除中断标志位//使能更新中断TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);/*配置中断*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择组2NVIC_InitStructure.NVIC_IRQChannel TIM2_IRQn;//定时器2在NVIC内的通道NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority 1;NVIC_Init(NVIC_InitStructure);TIM_Cmd(TIM2, ENABLE);//启动定时器
}
unsigned char time[] {22, 59, 30};
unsigned int date[] {2023, 12, 31};
char month[] {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
void Show_Time(void){OLED_ShowNum(1,1,time[0], 2);OLED_ShowString(1, 3, :);OLED_ShowNum(1,4,time[1], 2);OLED_ShowString(1, 6, :);OLED_ShowNum(1,7,time[2], 2);
}
void Show_Date(void){OLED_ShowNum(2,1,date[0], 4);OLED_ShowString(2, 5, /);OLED_ShowNum(2,6,date[1], 2);OLED_ShowString(2, 8, /);OLED_ShowNum(2,9,date[2], 2);
}
void Time_Control(void){time[2] time[2] 1;if(time[2] 60){time[2] 0;time[1] time[1] 1;if(time[1] 60){time[1] 0;time[0] time[0] 1;if(time[0] 24){time[0] 0;date[2] date[2] 1;if(date[2] month[date[1]] 1){date[2] 1;date[1] date[1] 1;if(date[1] 13){date[1] 1;date[0] date[0] 1;if(date[0] 9999){date[0] 2023;}}}}}}}void TIM2_IRQHandler(void){//定时器2的中断函数名字固定if(TIM_GetITStatus(TIM2, TIM_IT_Update) SET){TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清除标志位Time_Control();}}void month2_Control(void){//判别闰平年 if((date[0] % 4 0 date[0] % 100 ! 0 )|| date[0] % 400 0) month[2] 29;else month[2] 28;
}void Get_Hc05News(void){uint32_t i 0, j 0;while(j 10000){//等待中断while(Serial_GetRxFlag() 1){//查看标志位并清除News[i] Serial_GetRxData();//传入数据i ;j 0;flag 0;//标志传入了新数据}j ;}
}void Array_NewsClear(void){//恢复数组初始化uint16_t i 0;for(i 0; i 100; i ) News[i] \0;
}uint8_t StringLength(char * a){//计算数组长度函数uint8_t length 0;uint8_t i 0;while(a[i] ! \0){i ;length ;}return length;
}uint8_t Check(char *a, uint8_t length){if(length 5 | length 10){return 1;}return 0;
}int main(void){OLED_Init();//初始化OLEDTimer_Init();//开启计时器Serial_Init();//开启串口while(1){ Get_Hc05News();//时刻等待蓝牙传入数据if(flag 0){//蓝牙传入了数据//恢复标志位if(Check(News, StringLength(News)) 1){//若查看数据没有错误OLED_ShowString(3, 1, TRUE);OLED_ShowString(4, 1, News);Array_NewsClear();}else{OLED_ShowString(3, 1, FALSE);OLED_ShowString(4, 1, News);Array_NewsClear();}flag 1;}}
}
目前遇到的主要问题是OLED显示数字需要耗费时间导致蓝牙模块传入信息不能及时抢占CPU导致数据漏传入,解决方法是修改蓝牙模块中断为更高级中断
—— 2023/10/15 为了解决上述问题首先要将蓝牙传数据模块的中断抢占优先级调高这是为了防止计数器中断与其抢CPU
//将串口|蓝牙模块中断抢占优先级设置为3
NVIC_InitStructur.NVIC_IRQChannelPreemptionPriority 3;
NVIC_InitStructur.NVIC_IRQChannelSubPriority 1;调整之后传输数据明显丢包率小了许多但仍有数据丢失
原因在于主程序程序在未执行到if语句的时候是不会接受数据的
while(1){ if(Serial_GetRxFlag() 1){News Serial_returnNews();Delay_ms(100);OLED_ShowString(3, 1, News);Serial_RESETI();free(News);//释放空间必须释放否者发生地址紊乱直接卡机}Time_Show(time);Time_Show_Date(date);}但主程序又不能只执行这一个if语句 那么突破口在哪里呢我又想到数据传输在蓝牙模块的中断函数里这个函数很鸡肋每次只能接受一个字节那么为何不能让他把所有数据都一次性接收呢这就是突破口。
将数据都存入数组里
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);}
}这样就不用被动等待主函数里执行到if语句再一个一个接受数据了
还需要攻克的难题是如何将此数组返回至主函数
这里创建动态数组返回
char * Serial_returnNews(void){//返还一个数组char * array;uint8_t i 0;array (char *) malloc(sizeof(char) * 100);while(news[i] ! \0){array[i] news[i];i ;}OLED_ShowString(4,1,array:);OLED_ShowString(4,7,array);return array;
}主函数用一个char指针接收 但新的诡异问题又出现了数据接收很正确但是再连续接受几次数据后程序直接卡死这让我百思不得其解
问题出在没将创建的动态数组释放掉传入数据导致这些数据占据了大量空间导致Stm32地址不够用因为上述的返回数组函数没办法释放数组但这不代表在主函数里就不用释放
至此手机向蓝牙传输信息给Stm32的问题全部解决
全部工程代码
main.c://主函数
#include stm32f10x.h // Device header
#include Delay.h
#include OLED.h
#include Serial.h
#include Time.h
#include Function.h
#include stdio.h
#include stdlib.hchar *News NULL;//存数据
//uint8_t flag 1;//标志位
unsigned char time[] {22, 59, 30};
unsigned int date[] {2023, 12, 31};
char month[] {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};void TIM2_IRQHandler(void){//定时器2//主要运用时间更新if(TIM_GetITStatus(TIM2, TIM_IT_Update) SET){TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清除标志位Time_Control(time, month, date);}}int main(void){OLED_Init();//初始化OLEDTime_Init();//开启计时器Serial_Init();//开启串口while(1){ if(Serial_GetRxFlag() 1){News Serial_returnNews();Delay_ms(100);//等待数据传输完OLED_ShowString(3, 1, News);Serial_RESETI();free(News);//释放空间必须释放否者发生地址紊乱直接卡机}Time_Show(time);Time_Show_Date(date);}
}
Serial.c://串口初始化及传输数据函数等函数
#include stm32f10x.h // Device header
#include stdio.h
#include stdarg.h
#include Delay.h
#include stdlib.h
#include OLED.huint8_t Serial_RxData;//存数据
uint8_t Serial_RxFlag;//标志位
GPIO_InitTypeDef GPIO_InitStructu;//GPIO
USART_InitTypeDef USART_InitStructure;//串口
NVIC_InitTypeDef NVIC_InitStructur;//中断
//extern uint8_t flag;//全局定义
char news[100] ;//存数据
uint8_t I 0;void Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStructu.GPIO_Mode GPIO_Mode_AF_PP;GPIO_InitStructu.GPIO_Pin GPIO_Pin_9;GPIO_InitStructu.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructu);GPIO_InitStructu.GPIO_Mode GPIO_Mode_IPU;GPIO_InitStructu.GPIO_Pin GPIO_Pin_10;GPIO_InitStructu.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructu);USART_InitStructure.USART_BaudRate 9600;USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode USART_Mode_Tx | USART_Mode_Rx;USART_InitStructure.USART_Parity USART_Parity_No;USART_InitStructure.USART_StopBits USART_StopBits_1;USART_InitStructure.USART_WordLength USART_WordLength_8b;USART_Init(USART1, USART_InitStructure);USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//通道NVIC_InitStructur.NVIC_IRQChannel USART1_IRQn;//中断通道NVIC_InitStructur.NVIC_IRQChannelCmd ENABLE;NVIC_InitStructur.NVIC_IRQChannelPreemptionPriority 3;NVIC_InitStructur.NVIC_IRQChannelSubPriority 1;NVIC_Init(NVIC_InitStructur);USART_Cmd(USART1, ENABLE);
}uint8_t Serial_GetRxFlag(void)//读取标志位后自动青除
{if (Serial_RxFlag 1){Serial_RxFlag 0;return 1;}return 0;
}void Serial_GetRxFlag_SET(void){Serial_RxFlag 1;
}
uint8_t Serial_GetRxData(void)//返回一个字节
{return Serial_RxData;
}/*void Serial_GetNews(char *News){uint32_t i 0, j 0;while(j 10000){//等待中断while(Serial_GetRxFlag() 1){//查看标志位并清除News[i] Serial_GetRxData();//传入数据i ;j 0;flag 0;//标志传入了新数据}j ;}
}
*/
char * Serial_returnNews(void){//返还一个数组char * array;uint8_t i 0;array (char *) malloc(sizeof(char) * 100);while(news[i] ! \0){array[i] news[i];i ;}OLED_ShowString(4,1,array:);OLED_ShowString(4,7,array);return array;
}void Serial_RESETI(void){//初始化II 0;
}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);}
}Serial.h:
#ifndef __SERIAL_H
#define __SERIAL_H
#include stm32f10x.h
#include stdio.hvoid Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
void Serial_Printf(char *format, ...);
uint8_t Serial_GetRxFlag(void);
uint8_t Serial_GetRxData(void);
void Serial_GetRxFlag_SET(void);
//void Serial_GetNews(char *News);
char * Serial_returnNews(void);
void Serial_RESETI(void);#endif
Time.c://计数器初始化及显示时间日期等函数
#include stm32f10x.h
#include OLED.hTIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/*初始化通用定时器TIM2*/
void Time_Init(void){RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//APB1外设开启TIM_InternalClockConfig(TIM2);//选择内部时钟/*初始化时基单元*/TIM_TimeBaseInitStructure.TIM_ClockDivision TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode TIM_CounterMode_Up;//向上计数TIM_TimeBaseInitStructure.TIM_Period 10000 - 1;//ARR自动重装TIM_TimeBaseInitStructure.TIM_Prescaler 7200 - 1;//psc预分频器TIM_TimeBaseInitStructure.TIM_RepetitionCounter 0;//高级计时器内容直接给零//记录1s TIM_TimeBaseInit(TIM2, TIM_TimeBaseInitStructure);//刚初始化完就会进中断TIM_ClearFlag(TIM2, TIM_FLAG_Update);//消除中断标志位//使能更新中断TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);/*配置中断*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择组2NVIC_InitStructure.NVIC_IRQChannel TIM2_IRQn;//定时器2在NVIC内的通道NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority 1;NVIC_Init(NVIC_InitStructure);TIM_Cmd(TIM2, ENABLE);//启动定时器
}void Time_Control(unsigned char *time, char *month, unsigned int *date){//更新时间time[2] time[2] 1;if(time[2] 60){time[2] 0;time[1] time[1] 1;if(time[1] 60){time[1] 0;time[0] time[0] 1;if(time[0] 24){time[0] 0;date[2] date[2] 1;if(date[2] month[date[1]] 1){date[2] 1;date[1] date[1] 1;if(date[1] 13){date[1] 1;date[0] date[0] 1;if(date[0] 9999){date[0] 2023;}}}}}}}void Time_month2_Control(char *month,unsigned int *date){//判别闰平年 if((date[0] % 4 0 date[0] % 100 ! 0 )|| date[0] % 400 0) month[2] 29;else month[2] 28;
}void Time_Show(unsigned char *time){OLED_ShowNum(1,1,time[0], 2);OLED_ShowString(1, 3, :);OLED_ShowNum(1,4,time[1], 2);OLED_ShowString(1, 6, :);OLED_ShowNum(1,7,time[2], 2);
}
void Time_Show_Date(unsigned int *date){OLED_ShowNum(2,1,date[0], 4);OLED_ShowString(2, 5, /);OLED_ShowNum(2,6,date[1], 2);OLED_ShowString(2, 8, /);OLED_ShowNum(2,9,date[2], 2);
}
Time.h:
//显示时间日期
#ifndef __TIME_H
#define __TIME_H
#include stm32f10x.h
#include stdio.hvoid Time_Init(void);
void Time_Control(unsigned char *time, char *month, unsigned int *date);
void Time_month2_Control(char *month,unsigned int *date);
void Time_Show(unsigned char *time);
void Time_Show_Date(unsigned int *date);#endifFunction.c://需要用到的一些其他函数
#include stm32f10x.h
//一些函数的实现void Function_ArrayClear(char *News){//恢复数组初始化uint16_t i 0;for(i 0; i 100; i ) News[i] \0;
}uint8_t Function_ArrayLength(char * a){//计算数组长度函数uint8_t length 0;uint8_t i 0;while(a[i] ! \0){i ;length ;}return length;
}uint8_t Check(char *a, uint8_t length){//查数据长度是否符合条件if(length 5 | length 10){return 1;}return 0;
}Function.h:
#ifndef __FUNCTION_H
#define __FUNCTION_H
#include stm32f10x.h
#include stdio.hvoid Function_ArrayClear(char *News);
uint8_t Function_ArrayLength(char * a);
uint8_t Check(char *a, uint8_t length);#endif总体效果 —— 2023/10/16