/** * System monitor thread. * * @param parameter parameter */ void thread_entry_sys_monitor(void* parameter) { while (1) { if(get_system_status() == SYSTEM_STATUS_RUN){ /* elog test */ test_elog(); LED_RUN_ON; rt_thread_delay(DELAY_SYS_RUN_LED_ON); LED_RUN_OFF; rt_thread_delay(DELAY_SYS_RUN_LED_OFF); } else if (get_system_status() == SYSTEM_STATUS_INIT){ LED_RUN_ON; rt_thread_delay(DELAY_SYS_INIT_LED_ON); LED_RUN_OFF; rt_thread_delay(DELAY_SYS_INIT_LED_OFF); } else if (get_system_status() == SYSTEM_STATUS_FAULT){ LED_RUN_ON; rt_thread_delay(DELAY_SYS_FAULT_LED_ON); LED_RUN_OFF; rt_thread_delay(DELAY_SYS_FAULT_LED_OFF); } IWDG_Feed(); } }
/** * System monitor thread. * * @param parameter parameter */ void thread_entry_sys_monitor(void* parameter) { extern void cpu_usage_get(rt_uint8_t *major, rt_uint8_t *minor); while (1) { if(get_system_status() == SYSTEM_STATUS_RUN){ cpu_usage_get(&cpu_usage_major, &cpu_usage_minor); LED_RUN_ON; rt_thread_delay(DELAY_SYS_RUN_LED_ON); LED_RUN_OFF; rt_thread_delay(DELAY_SYS_RUN_LED_OFF); } else if (get_system_status() == SYSTEM_STATUS_INIT){ LED_RUN_ON; rt_thread_delay(DELAY_SYS_INIT_LED_ON); LED_RUN_OFF; rt_thread_delay(DELAY_SYS_INIT_LED_OFF); } else if (get_system_status() == SYSTEM_STATUS_FAULT){ LED_RUN_ON; rt_thread_delay(DELAY_SYS_FAULT_LED_ON); LED_RUN_OFF; rt_thread_delay(DELAY_SYS_FAULT_LED_OFF); } IWDG_Feed(); } }
/************************************************************************ ** 函数名:vIwdgTask ** 功 能:喂狗任务 ** 输 入:无 ** 输 出:无 ** 返 回:无 ** 备 注:无 ** 时 间: 2015年5月15日 17:04:12 ** 作 者:xsx ************************************************************************/ static void vIwdgTask( void *pvParameters ) { while(1) { IWDG_Feed(); vTaskDelay(500 * portTICK_RATE_MS); } }
/** * @brief 初始化独立看门狗 * @param prer : IWDG预分频值 , rlr 重装载值 * @retval None */ void IWDG_Init(u8 prer, u16 rlr) { IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //使能对寄存器IWDG_PR和IWDG_RLR的写操作 IWDG_SetPrescaler(prer); //设置IWDG预分频值:设置IWDG预分频值为64 IWDG_SetReload(rlr); //设置IWDG重装载值 IWDG_ReloadCounter(); //按照IWDG重装载寄存器的值重装载IWDG计数器 IWDG_Enable(); //使能IWDG IWDG_Feed(); }
/* *@功能:2字节用户编号+4字节RFID+6字节时间+1字节开锁结果,存入记录区 * * 每条长度为13字节 */ void save_rfid_result(void) //操作钥匙 { uint32_t record_addr; uint32_t Lock_number_addr; uint32_t total_row; uint8_t temp_Lock_number[4]; IWDG_Feed(); record_addr= SPI_FLASH_ReadWord(RECORD_POINT); //已存储的组数 SPI_FLASH_Write(User_Num,record_addr,2); //写查找到的授权的用户编号到记录中,如果没有找到则编号为零 SPI_FLASH_Write(Lock_number,record_addr+2,4); //写读到的RFID到记录中 read_time(); //读取实时时间,放到time_buff中 SPI_FLASH_Write(time_buff,record_addr+6,6); //写实时时间到time记录中 SPI_FLASH_Write(&unlock_result,record_addr+12,1); //写开锁结果到记录中 //for debug SPI_FLASH_Read(item,record_addr,13); UART1nSendChar(1,item,13); delay_ms(1000); record_addr=record_addr+RECORD_LEN; //每条授权RECORD_LEN=13字节 //更改授权用户信息指针的位置 SPI_FLASH_WriteWord(RECORD_POINT,record_addr); //for debug point=SPI_FLASH_ReadWord(RECORD_POINT); //RECORD_POINT=RECORD_START UART1SendwordHex(1, point); delay_ms(1000); //要区分宏地址里存放的内容到底是表示地址还是数据 total_row= SPI_FLASH_ReadWord(RECORD_ROW); total_row=total_row+1; //授权信息条数加一 SPI_FLASH_WriteWord(RECORD_ROW,total_row); //for debug row=SPI_FLASH_ReadWord(RECORD_ROW); UART1SendwordHex(1, row); delay_ms(1000); }
/* *@功能:检查读取到的锁码是否在授权文件当中 * * */ uint8_t check_lock_code(void) { uint8_t i,j,total_row; uint8_t known_lock_number[4]; uint32_t lock_number_addr,addr_end; uint8_t IN_AUTHOR_OFFSET=4; //RFID在一条授权中的偏移 addr_end= SPI_FLASH_ReadWord(AUTHOR_POINT); //在界面的采码功能里会改变采码指针的值 total_row=(addr_end-AUTHOR_START)/AUTHOR_LEN; // if(total_row==0) // { // UART1nSendChar(1,"没有授权文件",11); //如果total_row=0, // return 0; // } for(i=0;i<total_row;i++) // { lock_number_addr=AUTHOR_START+i*AUTHOR_LEN+IN_AUTHOR_OFFSET; SPI_FLASH_Read(known_lock_number,lock_number_addr,4); IWDG_Feed(); if(Lock_number[0]==known_lock_number[0]&&Lock_number[1]==known_lock_number[1]&&Lock_number[2]==known_lock_number[2]&&Lock_number[3]==known_lock_number[3]) { SPI_FLASH_Read(User_Num,lock_number_addr-4,2); //如果读到的RFID在授权中则记录下其用户编号 return 1; //读到了就返回1 } } User_Num[0]=0; User_Num[1]=0; return 0; }
/* *@功能:在空闲状态的几个任务 *1.检测是否有按键按下 *2.检测是否读到RFID *3.检测是否接受到串口传来的指令 *4.检测是否有USB连接到计算机上 *5.检测锂电池电压是否低电 共5个任务按各自的时间轴转动,基本上无冲突 */ void ST_Idle(void) { uint16_t ss_num=0; uint16_t power_num=0; uint16_t usb_bit; uint8_t key_r=KEYNO; uint8_t usb_r=0; uint8_t bt_r=0; uint8_t time_num=0; uint8_t p_c=0; uint8_t ss_flag=0; ResetKey(); //KeyNum是一个全局变量 //Init_KeyNumuber(); //Key_Num =KEYINIT //根据flsah中的信息,更改主菜单中的信息 SPI_FLASH_Read(HsMenu[1].Name,GROUP_INFORMATION,10); SPI_FLASH_Read(HsMenu[2].Name,KEY_INFORMATION,8); // //for debug // SPI_FLASH_Read(item,GROUP_INFORMATION,10); // UART1nSendChar(1,item,10); // delay_ms(1000); // //for dedug // SPI_FLASH_Read(item,KEY_INFORMATION,8); // UART1nSendChar(1,item,8); // delay_ms(1000); //for dedug // UART1nSendChar(1,HsMenu[1].Name,10); // delay_ms(1000); // UART1nSendChar(1,HsMenu[2].Name,8); // delay_ms(1000); OLED_Clear(); ShowMenuNoInverse(HsMenu); Main_Oled_Power(); Main_Oled_Time(); //Choose_MenuOp1(); //主界面显示 while(1) { // if(g_State!=ST_IDLE) // return; if(time_num==20) { Main_Oled_Time(); time_num=0; } ++time_num; delay_ms(50); //按键按下检测,如果有按键就按下就进入菜单操作 key_r =GetKey(); //判断是否有按键操作 if(ss_flag==0&&key_r==KEYNO) //超时关屏 { ss_num++; if(ss_num>=choosetime*6)//按下超过10秒钟 300/50=6 { OLED_Display_Off(); ss_flag=1; ss_num=0; } } if(ss_flag==1&&(key_r ==KEYCLEAR||key_r ==KEYSURE||key_r ==KEYDOWN||key_r == KEYUP)) { OLED_Display_On(); ss_flag=0; ResetKey(); key_r=KEYNO; } if(key_r !=KEYNO&&key_r !=KEYINIT) { //ResetKey(); //读完按键值后,将按键值复位 g_State =ST_LCDMENU; return; //按任意按键进入可选择菜单 } // //RFID检测 // nChar =Read_RfidData(2,Rfid_Buff,0xff); //非常重要的一点,是理解Trismit()的关键 // if(nChar >=3) // { // g_State =ST_KEY;return; //检测ID信息数据,如果读到了rfid数据,则将g_State置为st_key // } //检测上位机连接下位机命令,从菜单界面进入USB通信中 usb_r =UART1ReadFrm(1,g_Buff,MAX_BUFF); //USB串口1,g_Buff是一个全局变量;#define MAX_BUFF 520 if(usb_r==7&&g_Buff[0]==0xaa&&g_Buff[1]==0x75&&g_Buff[2]==0x0d&&g_Buff[3]==0x02&&g_Buff[4]==0x00&&g_Buff[5]==0x01&&g_Buff[6]==0xD1)//如果返回0x00就发下一条授权 { usb_bit=(USB_CHEAK&(GPIO_Pin_1))>>1; if(usb_bit==1) //USB插上 { bluetooth_uart_switch=0; pc_to_slave(); //上位机连接下位机的处理 g_State =ST_USB; //进入USB通信 return; } } bt_r =UART3ReadFrm(3,g_Buff,MAX_BUFF); //蓝牙串口2,g_Buff是一个全局变量;#define MAX_BUFF 520 if(bt_r==7&&g_Buff[0]==0xaa&&g_Buff[1]==0x75&&g_Buff[2]==0x0d&&g_Buff[3]==0x02&&g_Buff[4]==0x00&&g_Buff[5]==0x01&&g_Buff[6]==0xD1)//如果返回0x00就发下一条授权 { bluetooth_uart_switch=1; pc_to_slave(); //上位机连接下位机的处理;使用接受到的g_Buff // m_UB3; // m_UB3.RBuff; g_State =ST_USB; //进入USB通信 return; } usb_bit=(USB_CHEAK&(GPIO_Pin_1))>>1; if(usb_bit==1) //USB已经插上,即从蓝牙切换到USB bluetooth_uart_switch=0; //电池电量检测 power_num++; if( power_num==0x15) //0x15*20时Power_Cheak()才会返回有效值 { power_num =0; IWDG_Feed(); Main_Oled_Power(); //更新电池电量 p_c=Power_Cheak(); //此函数运行20次才返回有效值 if(p_c==4) //检测电池电压,如果电池电压过低,则进入关机模式,并进行提示 { // Main_Oled_Time(); // Main_Oled_Power(); OLED_Show_LowBattry(); //延时1s后关机 g_WaitTimeOut = 0; SetTimer(TIMER_TIMEOUT,100,Do_TimeOut,THREE_MIN); while( g_WaitTimeOut == 0 ) { IWDG_Feed(); } KillTimer(TIMER_TIMEOUT); Sys_Enter_Standby(); } } }
int main(void) { u8 readstatus,firstread=0; u8 humi_set_temp=humi_set; u8 temp_set_temp=temp_set; //main1(); /* USART1 config 115200 8-N-1 */ // USART1_Config(); // // printf("\r\n this is a yhx firmware \r\n"); /* 配置SysTick 为1us中断一次 */ SysTick_Init(); // TIM3_Int_Init(100,7199); DelayInit(); // delay_init(72); /*按键输入初始化*/ GPIO_INPUT_INIT(); /*输出初始化*/ IO_OUTPUT_Config(); /* I2C 外设初(AT24C02)始化 */ I2C_EE_Init(); /*当按下-键时,程序会执行默认的IP192.168.3.248,不会从eeprom读取数据*/ if( Key_Scan(KEYPORT,KEY_SUB,1) != KEY_ON ) I2C_EE_Restore(); if(EE_FLAG!=i2c_eeprom_data[0]) { //初始温湿度设定及裕量 i2c_eeprom_data[0]=EE_FLAG; i2c_eeprom_data[1]=temp_set; i2c_eeprom_data[2]=humi_set; i2c_eeprom_data[3]=temp_distance; i2c_eeprom_data[4]=humi_distance; //初始化net //ip i2c_eeprom_data[8]=ipaddress[0]; i2c_eeprom_data[9]=ipaddress[1]; i2c_eeprom_data[10]=ipaddress[2]; i2c_eeprom_data[11]=ipaddress[3]; //mask i2c_eeprom_data[12]=maskaddress[0]; i2c_eeprom_data[13]=maskaddress[1]; i2c_eeprom_data[14]=maskaddress[2]; i2c_eeprom_data[15]=maskaddress[3]; //gate i2c_eeprom_data[16]=gateaddress[0]; i2c_eeprom_data[17]=gateaddress[1]; i2c_eeprom_data[18]=gateaddress[2]; i2c_eeprom_data[19]=gateaddress[3]; //mac i2c_eeprom_data[24]=mymac[0]; i2c_eeprom_data[25]=mymac[1]; i2c_eeprom_data[26]=mymac[2]; i2c_eeprom_data[27]=mymac[3]; i2c_eeprom_data[28]=mymac[4]; i2c_eeprom_data[29]=mymac[5]; I2C_EE_WaitOperationIsCompleted(); I2C_EE_WriteBuffer(i2c_eeprom_data, 0, 8); //网络 I2C_EE_WaitOperationIsCompleted(); I2C_EE_WriteBuffer(i2c_eeprom_data+8, 8, 8); I2C_EE_WaitOperationIsCompleted(); I2C_EE_WriteBuffer(i2c_eeprom_data+16, 16, 8); I2C_EE_WaitOperationIsCompleted(); I2C_EE_WriteBuffer(i2c_eeprom_data+24, 24, 8); } //中断开启,配置net管脚和传感器data管脚中断 // NVIC_Configuration(); /*SHT10-模拟I2C读取温湿度,初始化*/ // Sht_GPIO_Config(); // s_connectionreset(); // sht10_read(); /*初始化DTT11的引脚*/ DHT11_GPIO_Config(); SPI1_Init(); //InitNet(); /* 初始化网络设备以及UIP协议栈,配置IP地址 */ //数码管初始化 hc595_init(); /* 配置SysTick 为10ms中断一次 */ // SysTick_Init(); TimingInput=0;//输入节拍20ms IWDG_Init(4,625); //与分频数为64,重载值为625,溢出时间为1s while(1) { /*温湿度测量,massureflag请求测量标志*/ if(massureflag) { //数据伪造1213,温度控制用的是真实的,显示和上传的数据用的是渐变的伪造数据 if( (readstatus=Read_DHT11(&DHT11_Data))==SUCCESS) { if(firstread==0) { temp_val.f=DHT11_Data.temp_int; firstread=1; } else { if(DHT11_Data.temp_int>(int)temp_val.f) temp_val.f=temp_val.f+0.5; else if(DHT11_Data.temp_int<(int)temp_val.f) temp_val.f=temp_val.f-0.5; } humi_val.f=DHT11_Data.humi_int; sensor_error=0; massureflag=0; time18ms_out=0; if(set_wait>1000)//初始化已过 if((temp_val.f>-10)&&(temp_val.f<100)&&(humi_val.f>=0/*)&&(humi_val.f<100*/)&&poweron)//传感器没坏才输出 automation(); }else if(readstatus!=NOTREADY) { sensor_error++; } } if(sensor_error>5)//5次都没有采到温湿度 { temp_val.f=humi_val.f=-100; } //printf("温度:%.1f\t湿度%.1f\r\n",temp_val.f,humi_val.f); //根据检测到的温湿度控制led和继电器,刚开机3s的时候尚未检测到温湿度,此时最好不要有输出,在while之前添加sht10_read()吧,进来之前就读一次数据 if((0==poweron)||((time_s_remainder==0)&&(active!='a'))) { WARM(0); WARM_LED(0); COLD(0); COLD_LED(0); WET(0); WET_LED(0); ALWAYS_WET_LED(0); BEEP_SCREAM(0); work_state=0; } if(network_state==0) { //下面的代码是按键检测,用来设定温湿度设定值的 if(TimingInput)//输入检测20ms一次 { TimingInput=0; key_input_last=key_input; GPIO_INPUT_SCAN(); if(key_input==key_input_last)//检测是否一直按着同一个按键 press_same_key_flag=1;//一直按着同一个按键 else press_same_key_flag=0; //蜂鸣器响应 if((key_input)&&(beeptime<300)) { //蜂鸣器响 BEEP_SCREAM(1); }else { if(key_input==0) beeptime=0; //蜂鸣器关闭 BEEP_SCREAM(0); } //是否进入设定状态,闪烁。 if(0==showdigital)//之前就是闪烁状态,temp_set_temp数据要保留 { temp_set_temp=temp_set; humi_set_temp=humi_set; } if((0==press_same_key_flag)&&(0!=key_input))//有按键按下但不是同一个按键 { //输入处理 switch (key_input) { case 1://set if(set_wait<=1000) set_start_flag=1; showdigital++;//第showdigital位闪烁 if(showdigital>4) showdigital=1; break; case 2://save showdigital=0; set_start_flag=0;//初始化完成标志 set_wait=1001;//设置等待10s结束 //将数据保存到eeprom,温湿度设定值 temp_set=temp_set_temp; humi_set=humi_set_temp; i2c_eeprom_data[1]=temp_set; i2c_eeprom_data[2]=humi_set; //写入eeprom i2c_eeprom_data[0]=EE_FLAG; I2C_EE_WaitOperationIsCompleted(); I2C_EE_WriteBuffer(i2c_eeprom_data, 0, 5); break; case 4://+ //第showdigital位+ switch(showdigital) { case 1: temp_set_temp=(temp_set_temp/10+1)%10*10+temp_set_temp%10; break; case 2: temp_set_temp=temp_set_temp/10*10+(temp_set_temp%10+1)%10; break; case 3: humi_set_temp=(humi_set_temp/10+1)%10*10+humi_set_temp%10; break; case 4: humi_set_temp=humi_set_temp/10*10+(humi_set_temp%10+1)%10; break; default:; } break; case 8://- //第showdigital位+ switch(showdigital) { case 1: temp_set_temp=(temp_set_temp<10)?90+temp_set_temp:(temp_set_temp/10-1)%10*10+temp_set_temp%10; break; case 2: temp_set_temp=(temp_set_temp%10==0)?temp_set_temp+9:temp_set_temp-1; break; case 3: humi_set_temp=(humi_set_temp<10)?90+humi_set_temp:(humi_set_temp/10-1)%10*10+humi_set_temp%10; break; case 4: humi_set_temp=(humi_set_temp%10==0)?humi_set_temp+9:humi_set_temp-1; break; default:; } break; default:; } } } }else {//本地状态显示 humi_set_temp=humi_set; temp_set_temp=temp_set; key_input=0; showdigital=0; BEEP_SCREAM(0); beeptime=0; } //试用期写入 if((active!='a')&&(remainder_write>300)) { remainder_write=0; //写入eeprom //if(time_s_remainder>0) { i2c_eeprom_data[32]=(u8)time_s_remainder; i2c_eeprom_data[33]=(u8)(time_s_remainder>>8); i2c_eeprom_data[34]=(u8)(time_s_remainder>>16); i2c_eeprom_data[35]=(u8)(time_s_remainder>>24); I2C_EE_WaitOperationIsCompleted(); I2C_EE_WriteBuffer(i2c_eeprom_data+32, 32, 4); } } //sht10_j: //数码管输出 digitaldata[0]=digitaldata[1]=digitaldata[2]=digitaldata[3]=digitaldata[4]=digitaldata[5]=12;//12 if((active=='a')||(time_s_remainder>0))//激活态20150421 { //温度 if((temp_val.f<0)&&(temp_val.f>-10))//负值 { digitaldata[0]=10;//- digitaldata[1]=(u8)(-temp_val.f); digitaldata[2]=(u8)(-temp_val.f*10)%10; }else if((temp_val.f>=0)&&(temp_val.f<100))//正数 { digitaldata[0]=((u8)temp_val.f)/10; digitaldata[1]=((u8)temp_val.f)%10;//. digitaldata[2]=(u8)(((u16)(temp_val.f*10))%10); } //湿度 if(humi_val.f>=0)//((humi_val.f>=0)&&(humi_val.f<100)) { if(humi_val.f>=100) { temp_f=humi_val.f;//20150712 add temp xzk humi_val.f=99.9; } digitaldata[3]=((u8)humi_val.f)/10; digitaldata[4]=((u8)humi_val.f)%10;//. digitaldata[5]=(u8)(((u16)(humi_val.f*10))%10); if(humi_val.f>=99.9) humi_val.f=temp_f; } }else //试用期已经到了,显示off 20150421 { digitaldata[0]=0; digitaldata[3]=0; BEEP_SCREAM(1); } //设定温度值 digitaldata[6]=temp_set_temp/10; digitaldata[7]=temp_set_temp%10; //湿度设定 digitaldata[8]=humi_set_temp/10; digitaldata[9]=humi_set_temp%10; if((blickflag)&&(network_state==0))//可以闪烁 switch(showdigital) {//showdigital=0//低位到高位是否显示6 7 8 9,0都显示,1:9不显示;2:8不显示;3:7不显示;4:6不显示 case 1: digitaldata[6]=11; break; case 2: digitaldata[7]=11; break; case 3: digitaldata[8]=11; break; case 4: digitaldata[9]=11; break; default:; } hc595_display(digitaldata); //就地状态或网络状态PC3 if( Key_Scan(GPIOC,GPIO_Pin_3,0) == KEY_ON ) { /*按键有效*/ network_state=1; }else//就地 { network_state=0; //poweron=1; //0716 //启动开关PA12检测 20150719 if( Key_Scan(GPIOA,GPIO_Pin_12,1) == KEY_ON ) { poweron=1; }else { poweron=0; } } /* 下面是网络检测的程序,处理uip事件,必须插入到用户程序的循环体中 */ UipPro(); //中断触发读取网络接收缓存 eth_poll(); //定时查询TCP及UDP连接收发状态 ARP表更新, 并响应 IWDG_Feed();//喂狗 if(request_initnet>250)//等待2s初始化网络 { InitNet(); request_initnet=0; } }
void Key_Trismit(void) { uint8_t i,nChar; //AA 75 +11+06+00 +ID +4字节RFID+1字节校验位 uint8_t PDA_RFID[11]={0xAA,0x75,0x11,0x06,0x00,0x01,0x00,0x00,0x00,0x00,0x00}; //在ST_Idle()中已经检测到了RFID,才会调到这里 for(i =0;i<4;i++) //Lock_number[4]和Rfid_Buff[6]都是全局变量 Lock_number[i] =Rfid_Buff[i]; //在ST_Idle()中已经将数据放入Rfid_Buff[] for(i =0;i<4;i++) //Lock_number[4]和Rfid_Buff[6]都是全局变量 PDA_RFID[i+6] =Rfid_Buff[i]; //在ST_Idle()中已经将数据放入Rfid_Buff[] PDA_RFID[10]=PDA_RFID[0]^PDA_RFID[1]^PDA_RFID[2]^PDA_RFID[3]^PDA_RFID[4]^PDA_RFID[5]^PDA_RFID[6]^PDA_RFID[7]^PDA_RFID[8]^PDA_RFID[9]; //传递RFID锁的编号,靠UART2串口中断,将RFID数据放到放到缓冲区, //再由read_RfidData将数据读入Rfid_Buff[],这个函数在ST_Idle()中调用过 IWDG_Feed(); OLED_Clear(); OLED_ShowUnite(16,2,"ID:"); OLED_ShowNumHex(48,2,Lock_number[0],2,16); OLED_ShowNumHex(64,2,Lock_number[1],2,16); OLED_ShowNumHex(80,2,Lock_number[2],2,16); OLED_ShowNumHex(96,2,Lock_number[3],2,16); //OLED_ShowUnite(16,4,"核对授权中"); nChar= check_lock_code(); //匹配就为1;不匹配就为0 //UART1nSendChar(1,&nChar,1); //UART1nSendChar(1,"22222",5); //nChar =1; //只有读取的锁码在授权文件中,才返回1 if(nChar ==0) { OLED_ClearArea(0,4,128,6); OLED_ShowUnite(36,4,"未授权"); buzzer_unlock_fail(); delay_ms(1500); unlock_result=2; //返回授权中需要的状态结果 save_rfid_result(); //将锁码及开锁状态写入存储芯片中 g_State =ST_IDLE; unlock_result=2; //返回授权中需要的状态结果 return; } else if(nChar==1) { IWDG_Feed(); UART3nSendChar(3,PDA_RFID,11); buzzer_unlock_success(); COIL_ACTUATE; OLED_ClearArea(0,4,128,6); OLED_ShowUnite(36,4,"已授权"); delay_ms(1000); unlock_result=1; save_rfid_result(); //将锁码及开锁状态写入存储芯片中 COIL_NO_ACTUATE;//关闭SPX2941电源,即关闭钥匙动作过程 //UART1nSendChar(1,"33333",5); g_State =ST_IDLE; IWDG_Feed(); UART2Reset(2); return; } }
/* *@功能:读取按协议格式发送过来的数据,并进行解析 */ uint8_t UART3ReadFrm(uint8_t uart, uint8_t *pdst, uint32_t max) { uint8_t count = 0,total; uint8_t idx,off; IWDG_Feed(); USART_ITConfig(USART3, USART_IT_RXNE, DISABLE); //关接收中断,在接受中断USART1_IRQHandler()不断的将接受的数据放在m_UB1 if(m_UB3.cRHead != m_UB3.cRTail) { //计算有效数据总长度;得到数据时head会增加 if (m_UB3.cRHead >= m_UB3.cRTail) //如果头大于尾 { total = m_UB3.cRHead - m_UB3.cRTail; } else { total = UARTRXLEN3 + m_UB3.cRHead - m_UB3.cRTail ; //如果尾大于头 } //找结束符 if (total>4)//帧长度至少为4 { if (m_UB3.RBuff[m_UB3.cRTail]!=(uint8_t)0xaa) // { m_UB3.cRTail = (m_UB3.cRTail+1)% UARTRXLEN3; //UARTRXLEN为254,cRTail加1 } else { off = (m_UB3.cRTail + 1) % UARTRXLEN3; //cTail的下一个位置的地址 if (m_UB3.RBuff[off]!=(uint8_t)0x75) { m_UB3.cRTail = (m_UB3.cRTail+2)% UARTRXLEN3; //再将cTail加1 } else //表示接收到的第一个数aa,第二个数75 { off = (m_UB3.cRTail + 3) % UARTRXLEN3; //off表示第3个数,cRTail没有变 count=m_UB3.RBuff[off]+5; //5表示开头2个字符,1个命令字,1个长度,0x00 // count = m_UB1.RBuff[off]<<8;//数据长度高字节 表示取第三个数的高8位 // off = (m_UB1.cRTail + 4) % UARTRXLEN;//off表示第4个数 // count = count + m_UB1.RBuff[off]+7;//数据长度低字节,两者相加后count表示整个数据长度,7表示2个开头字符,1个命令字,2个长度,0x00,检验位 if (count <= total && count < max) //total是缓冲区有效数据的长度,count是整个命令帧的长度,所以永远有count<total { //数据长度满足一帧的要求 //total = 0;//纪录校验和,total换了一种含义 for (idx=0; idx < max-1 && idx<count;idx++) { off = (m_UB3.cRTail + idx) % UARTRXLEN3; //cRTail也没有变 pdst[idx] = m_UB3.RBuff[off]; ////将接受缓冲区的按命令帧存入pdst数组 //total ^= pdst[idx];//计算校验和 } // if (total==0)//校验正确,此处为奇校验 m_UB3.cRTail = (off + 1) % UARTRXLEN3; //校验正确就将cRTail放在整个数据帧的下一个位置 // else // { // //校验错误,抛弃2个字节,其实为本帧的头 // m_UB1.cRTail = (m_UB1.cRTail + 2) % UARTRXLEN; // count = 0; // } } else count =0; } } } } USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); IWDG_Feed(); return count; }