Files
stm32-cnn/HARDWARE/EC800/EC800M.c
2024-12-19 14:06:05 +08:00

417 lines
15 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "EC800M.h"
#include "usart.h"
#include "delay.h"
#include "sdram.h"
#include "stm32f4xx.h"
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include "cnn.h"
unsigned char Flag_topic;
extern UART_BUF buf_uart2; //NBIOT
extern UART_BUF buf_uart1; //TTL
char *strx,*extstrx;
CSTX_4G CSTX_4G_Status; //模块的状态信息
int errcount=0; //发送命令失败次数 防止死循环
int errCountData=0;
char ATSTR[BUFLEN]; //组建AT命令的函数
char IMEINUMBER[BUFLEN];//+CGSN: "869523052178994"
#define DESTINATION_SIZE 256
char *strx,*extstrx;
char destination[DESTINATION_SIZE];
/*云端下发的时间*/
int month_def = 1;
int date_def = 0;
int hour_def = 0;
int min_def = 0;
int sec_def= 0;
////////////////////////只要修改三要素/////////////////////////////////
#define PRODUCEKEY "k16dsL76w8K" //修改产品秘钥
#define DEVICENAME "device_1" //修改设备名称
#define DEVICESECRET "b36d0f9e35c7fede452a85c59473a411" //设备的API
void Clear_Buffer(uint16_t *USARTx_RX_STA, uint8_t *USARTx_RX_BUF) {
delay_ms(300);
memset(USARTx_RX_BUF, 0, USART_REC_LEN);
*USARTx_RX_STA = 0;
}
void extract_IMSI(uint8_t *input_str, char *output_str) {
char *start_ptr = strstr((char *)input_str, "460");
if (start_ptr != NULL) {
strncpy(output_str, start_ptr, 15);
output_str[15] = '\0'; // 添加字符串结束符
} else {
output_str[0] = '\0';
}
}
/*****************************************************
初始化模块 和单片机连接,获取卡号和信号质量
*****************************************************/
uint8_t CSTX_4G_Init(void)
{
//打印初始化信息
printf("start init EC800X\r\n");
//发第一个命令ATE1
Uart2_SendStr("ATE1\r\n");
delay_ms(200);
strx = strstr((char*)USART2_RX_BUF, "OK");
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
while(strx==NULL)
{
printf("单片机正在连接模块......\r\n");
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
Uart2_SendStr("\n\rATE1\r\nATE1");
delay_ms(300);
strx = strstr((char*)USART2_RX_BUF, "OK");
// if(errcount++ > 10) {
// printf("\r\n未连接到模块\r\n");
// return 0;
// }
}
printf("****单片机和模块连接成功*****\r\n");
Uart2_SendStr("ATI\r\n");//获取模块的版本
delay_ms(30);
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
Uart2_SendStr("AT+CIMI\r\n");//获取卡号,类似是否存在卡的意思,比较重要。
delay_ms(30);
strx = strstr((char*)USART2_RX_BUF, "460");
while(strx==NULL)
{
printf("****获取卡号*****\r\n");
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
Uart2_SendStr("AT+CIMI\r\n");//获取卡号,类似是否存在卡的意思,比较重要。
delay_ms(30);
strx = strstr((char*)USART2_RX_BUF, "460");
printf("%s",USART2_RX_BUF);
}
char output_str[16];
extract_IMSI(USART2_RX_BUF, output_str);
printf("我的卡号是 : %s \r\n",output_str);
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
Uart2_SendStr("AT+CGATT?\r\n");//查询激活状态
delay_ms(30);
strx = strstr((char*)USART2_RX_BUF, "+CGATT: 1");
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
while(strx==NULL)
{
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
Uart2_SendStr("AT+CGATT?\r\n");//获取激活状态
delay_ms(30);
strx = strstr((char*)USART2_RX_BUF, "+CGATT: 1");
}
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
Uart2_SendStr("AT+CSQ\r\n");//查看获取CSQ值
delay_ms(30);
strx = strstr((char*)USART2_RX_BUF, "+CSQ:");
if(strx)printf("信号质量是:%s 注意信号最大值是31 \r\n",USART2_RX_BUF);
return 1;
}
/*****************************************************
收到服务器下发的数据就直接打印 +QMTRECV: 0,0,"$creq/a19d2d64-3ee3-5070-8078-ad43e10a52f0","LED11"
*****************************************************/
unsigned char CSTX_4G_RECData(void)
{
strx=strstr((const char*)USART2_RX_BUF,(const char*)"+QMTRECV");//返回+QMTRECV:,表明接收到服务器发回的数据
if(strx)
{
delay_ms(300); // 必须延时
strncpy(destination, (char *)USART2_RX_BUF, DESTINATION_SIZE - 1);
destination[DESTINATION_SIZE - 1] = '\0';
TimeInfo TimeInfo = parseTimeInfo(destination);
month_def =TimeInfo.month;
date_def =TimeInfo.day;
hour_def =TimeInfo.hour;
min_def =TimeInfo.minute;
sec_def =TimeInfo.second;
printf(" Month: %d, Day: %d, Hour: %d, Minute: %d, Second: %d\r\n",
TimeInfo.month, TimeInfo.day, TimeInfo.hour, TimeInfo.minute, TimeInfo.second);
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
return 1;
}
return 0;
}
/*****************************************************
注册到ONENET topic = 0 -> 自定义topic 用于准备接收下发的时间 topic = 1 -> 物模型topic 用于上传数据
*****************************************************/
void CSTX_4G_RegALiYunIOT(unsigned char topic)//平台注册
{
int errcount = 0;
static unsigned char flag=0;
if(flag == 0){
printf("****初始化完成*****\r\n\r\n");
Uart2_SendStr("AT+QMTDISC=0\r\n");//Disconnect a client from MQTT server
delay_ms(30);
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
Uart2_SendStr("AT+QMTCLOSE=0\r\n");//删除句柄
delay_ms(30);
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
delay_ms(30);
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
Uart2_SendStr("AT+QMTCFG=\"version\",0,4\r\n");//切换下版本
delay_ms(30); //等待300ms反馈OK
strx = strstr((char*)USART2_RX_BUF, "OK");
while(strx==NULL)
{
strx = strstr((char*)USART2_RX_BUF, "OK");
}
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
memset(ATSTR,0,BUFLEN);
sprintf(ATSTR,"AT+QMTCFG=\"ALIAUTH\",0,\"%s\",\"%s\",\"%s\"\r\n",PRODUCEKEY,DEVICENAME,DEVICESECRET); //+QMTCONN: 0,0,0
printf("ATSTR = %s \r\n",ATSTR);
Uart2_SendStr(ATSTR);
delay_ms(30);
strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTOPEN: 0,0 +QMTOPEN: 0,0
while(strx==NULL)
{
errcount++;
delay_ms(30);
strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返回OK
if(errcount>10000) //防止死循环
{
NVIC_SystemReset(); //没有创建TCP SOCKET就重启系统等到服务器就绪
}
}
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
Uart2_SendStr("AT+QMTOPEN=0,\"iot-as-mqtt.cn-shanghai.aliyuncs.com\",1883\r\n");//切换下版本
delay_ms(30); //等待300ms反馈OK
strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返OK
while(strx==NULL)
{
strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返OK
}
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
Uart2_SendStr("AT+QMTCONN=0,\"-test-\"\r\n");//切换下版本
delay_ms(30); //等待300ms反馈OK
strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返OK
while(strx==NULL)
{
strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返OK
printf("连接中……\r\n");
}
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
}
flag = 1;
if(topic == 0){
if(Flag_topic == 1){
memset(ATSTR,0,BUFLEN);
sprintf(ATSTR,"AT+QMTUNS=0,100,\"/%s/%s/user/Set_time\"\r\n",PRODUCEKEY,DEVICENAME); //+QMTCONN: 0,0,0
printf("ATSTR = %s \r\n",ATSTR);
Uart2_SendStr(ATSTR);//发送链接到阿里云
delay_ms(30);
strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0
while(strx==NULL)
{
strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0
}
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
}
memset(ATSTR,0,BUFLEN);
sprintf(ATSTR,"AT+QMTSUB=0,1,\"/%s/%s/user/Set_time\",0\r\n",PRODUCEKEY,DEVICENAME); //+QMTCONN: 0,0,0
printf("ATSTR = %s \r\n",ATSTR);
Uart2_SendStr(ATSTR);//发送链接到阿里云
delay_ms(30);
strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0
while(strx==NULL)
{
strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0
}
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
Flag_topic = 0;
}
else if(topic == 1){
memset(ATSTR,0,BUFLEN);
sprintf(ATSTR,"AT+QMTUNS=0,100,\"/%s/%s/user/Set_time\"\r\n",PRODUCEKEY,DEVICENAME); //+QMTCONN: 0,0,0
printf("ATSTR = %s \r\n",ATSTR);
Uart2_SendStr(ATSTR);//发送链接到阿里云
delay_ms(30);
strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0
while(strx==NULL)
{
strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0
}
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
memset(ATSTR,0,BUFLEN);
sprintf(ATSTR,"AT+QMTSUB=0,1,\"/%s/%s/thing/event/property/set\",0\r\n",PRODUCEKEY,DEVICENAME); //+QMTCONN: 0,0,0
printf("ATSTR = %s \r\n",ATSTR);
Uart2_SendStr(ATSTR);//发送链接到阿里云
delay_ms(30);
strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0
while(strx==NULL)
{
strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0
}
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
Flag_topic = 1;
}
}
uint16_t MakeALiYunPayload_s(char *Str,char *Data, const char* identifier)
{
// Onenet有效载荷固定格式的模板
const char PayloadTemplate[60] = "{\"id\":\"123\",\"version\":\"1.0\",\"params\":{\"%s\":{\"value\":\"%s\"}}}";
char JsonBuf[BUFLEN]; // 临时数据缓存
unsigned int StrLen; // 有效载荷数据长度
// 使用snprintf将Data和identifier插入到PayloadTemplate中
snprintf(JsonBuf,sizeof(JsonBuf),PayloadTemplate,identifier,Data);
// 计算有效载荷的数据长度
StrLen = strlen((const char*)JsonBuf); // strlen返回的是字节数无需再除以sizeof(char)
// 拷贝有效载荷数据到Str
memcpy(Str, JsonBuf, StrLen);
// 返回长度
return StrLen;
}
void convert_to_string(uint8_t *Send_Json, char *output_str, size_t length)
{
// 将 uint8_t 数组转换为字符串
memcpy(output_str, Send_Json, length);
output_str[length] = '\0'; // 添加字符串结束符
}
void CSTX_4G_ALiYunIOTSenddata_string(char *Data,const char* identifier)//上发数据,上发的数据跟对应的插件有关系,用户需要注意插件然后对应数据即可
{
static char Send_buff[BUFLEN];//AT命令临时缓存
u16 JsonLen; // Json包数据长度
memset((char *)Send_buff, 0, BUFLEN); // 开辟数据缓存 //开辟数据缓存 sprintf((char*)Json,"{\"Temp\":%d,\"Humi\":%d}",Temperature,Humidity);//拷贝数据 装订联网三要素 Temperature,Humidity
memset(ATSTR,0,BUFLEN);
JsonLen = MakeALiYunPayload_s(Send_buff,Data, identifier); //得到json
memset(ATSTR,0,BUFLEN);
sprintf(ATSTR,"AT+QMTPUBEX=0,0,0,0,\"/sys/%s/%s/thing/event/property/post\",%d\r\n",PRODUCEKEY,DEVICENAME,JsonLen);
printf("ATSTR = %s \r\n",ATSTR);
Uart2_SendStr(ATSTR);//mqtt订阅
strx=strstr((const char*)USART2_RX_BUF,(const char*)">");//准备发送数据
errcount=0;
while(strx==NULL)
{
errcount++;
strx=strstr((const char*)USART2_RX_BUF,(const char*)">");//准备发送数据 模块的反馈
delay_ms(10);
if(errcount>100) //超时退出
{
errcount = 0;
break;
}
}
printf("Data数据为:%s\r\n",Send_buff);
delay_ms(50);
Uart2_SendStr(Send_buff);
// 发送JSON数据
delay_ms(50);
// 等待发送完成响应
errcount = 0;
strx = strstr((const char*)USART2_RX_BUF, (const char*)"+QMTPUBEX: 0,0,0"); // 返SEND OK +QMTPUB: 0,0,0
while (strx == NULL)
{
errcount++;
strx = strstr((const char*)USART2_RX_BUF, (const char*)"+QMTPUBEX: 0,0,0"); // 返SEND OK
delay_ms(100);
if (errcount > 10) // 超时退出
{
printf("发送数据超时!\n");
errcount = 0;
break;
}
}
Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF);
}
// 解析函数实现
TimeInfo parseTimeInfo(const char *jsonString) {
TimeInfo TimeInfo = {0}; // 初始化结构体为0
// 查找JSON字符串中"params"部分的起始位置
const char *paramsStart = strstr(jsonString, "\"params\"");
if (paramsStart != NULL) {
// 创建一个临时缓冲区来复制JSON的"params"部分(注意,这里为了简化处理,直接使用了静态缓冲区)
char TempBuffer[256];
strncpy(TempBuffer, paramsStart, sizeof(TempBuffer) - 1);
TempBuffer[sizeof(TempBuffer) - 1] = '\0';
// 使用简单的字符串解析来提取时间信息(注意,这种方法很脆弱,仅适用于格式固定的字符串)
char *token;
token = strtok(TempBuffer, ",\"{}:");
while (token != NULL) {
if (strcmp(token, "date") == 0) {
token = strtok(NULL, ",\"{}:");
TimeInfo.day = atoi(token); // JSON中"date"实际上是日这里暂存到day字段
} else if (strcmp(token, "month") == 0) {
token = strtok(NULL, ",\"{}:");
TimeInfo.month = atoi(token);
} else if (strcmp(token, "year") == 0) {
// JSON中没有直接的"year"字段,但我们可以从其他信息中推断,或者假设一个默认的年份(这里不处理)
// 或者如果"date"和"month"存在,且你有某种方式知道是哪一年(比如当前年份),你可以在这里设置它
} else if (strcmp(token, "hour") == 0) {
token = strtok(NULL, ",\"{}:");
TimeInfo.hour = atoi(token);
} else if (strcmp(token, "minute") == 0) {
token = strtok(NULL, ",\"{}:");
TimeInfo.minute = atoi(token);
} else if (strcmp(token, "second") == 0) {
token = strtok(NULL, ",\"{}:");
TimeInfo.second = atoi(token);
}
token = strtok(NULL, ",\"{}:");
}
// 注意:上面的代码没有处理"year"字段因为你的示例JSON中没有提供。
// 你需要根据实际情况来处理这个字段,比如使用当前年份,或者从其他来源获取年份信息。
// 这里为了示例我们假设年份是固定的比如2024年你可以在实际代码中修改这个值。
TimeInfo.year = 2024; // 假设的年份,根据实际情况修改
}
return TimeInfo;
}
///重定向c库函数scanf到串口重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{ RX1_len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
/* 等待串口输入数据 */
while (__HAL_UART_GET_FLAG(&UART1_Handler, UART_FLAG_RXNE) == RESET);
//while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
return (int)HAL_UART_Receive(&UART1_Handler,(uint8_t*)USART_RX_BUF,RX1_len,1000);
//return (int)USART_ReceiveData(USART1);
}