#include <Arduino.h>
#include <LiquidCrystal.h>
// -------- LCD parallel 20x4: RS,E,D4,D5,D6,D7 --------
LiquidCrystal lcd(PA0, PA1, PB0, PB1, PA4, PA5);
#define LCD_COLS 20
// -------- UART1 loop (PA9->PA10) --------
HardwareSerial U(PA10, PA9); // RX, TX
// -------- Режимы --------
#define MODE_IDLE 0
#define MODE_GSM 1
#define MODE_GPS 2
#define MODE_BLE 3
uint8_t modeCur = MODE_IDLE;
// -------- Таймеры --------
unsigned long tSend = 0;
const unsigned GSM_PERIOD=4000, GPS_PERIOD=1000, BLE_PERIOD=2000;
// -------- Буферы --------
char rxLine[160]; int rxLen=0;
char cli[16]; int cliLen=0;
// -------- Мелкие утилиты печати --------
void lcdPuts(const char* s){ while(*s) lcd.write(*s++); }
void lcdPrintInt(int v){
char b[12]; int i=0,neg=0; if(v<0){neg=1; v=-v;}
do{ b[i++]='0'+(v%10); v/=10; }while(v&&i<10);
if(neg) b[i++]='-'; while(i--) lcd.write(b[i]);
}
void lcdPrintDec5(int v){ // печать v/100000
if(v<0){ lcd.write('-'); v=-v; }
lcdPrintInt(v/100000); lcd.write('.'); int f=v%100000;
char z[5]={ char('0'+f/10000), char('0'+(f/1000)%10), char('0'+(f/100)%10), char('0'+(f/10)%10), char('0'+f%10) };
for(int i=0;i<5;i++) lcd.write(z[i]);
}
void lcdPrintDec1(int v){ // печать v/10
if(v<0){ lcd.write('-'); v=-v; }
lcdPrintInt(v/10); lcd.write('.'); lcd.write('0'+(v%10));
}
// -------- Парсинг NMEA в целых --------
static inline bool startsWith(const char* s,const char* p){ while(*p){ if(*s++!=*p++) return false; } return true; }
int toInt2(const char* p){ return (p[0]-'0')*10+(p[1]-'0'); }
int toInt3(const char* p){ return (p[0]-'0')*100+(p[1]-'0')*10+(p[2]-'0'); }
int nmeaDeg5(const char* s,int degDigits){
int deg=0; for(int i=0;i<degDigits;i++) deg=deg*10+(s[i]-'0');
const char* p=s+degDigits; int mm=toInt2(p); int mmm=toInt3(p+3);
int milli=mm*1000+mmm; int add=(milli*5+1)/3; return deg*100000+add;
}
// -------- Вывод на LCD --------
void setMode(uint8_t m){
modeCur=m; tSend=0; lcd.clear(); lcd.setCursor(0,0);
if(m==MODE_GSM) lcdPuts("MODE: GSM");
else if(m==MODE_GPS) lcdPuts("MODE: GPS");
else if(m==MODE_BLE) lcdPuts("MODE: BLE");
else lcdPuts("MODE: IDLE");
}
void showGsm(const char* s){
const char* p=s+8; const char* c=strchr(p,':'); const char* q1=strchr(c?c:"",'"'); const char* q2=q1?strrchr(q1+1,'"'):0;
if(!c||!q1||!q2||q2<=q1) return;
lcd.clear();
lcd.setCursor(0,0); lcdPuts("SMS from:");
lcd.setCursor(0,1); while(p<c) lcd.write(*p++);
lcd.setCursor(0,2); lcdPuts("Message text:");
lcd.setCursor(0,3); for(const char* t=q1+1; t<q2 && (t-(q1+1))<LCD_COLS; ++t) lcd.write(*t);
}
void showGps(const char* s){
const char* gpr=strstr(s,"$GPRMC"); if(!gpr) return;
const char* f[12]={0}; int fi=0; const char* p=gpr;
for(;*p&&fi<12;++p) if(*p==','||*p=='*') f[fi++]=p;
if(fi<10) return;
char stat=*(f[2]+1);
const char* lat=f[3]+1; const char* NS=f[4]+1;
const char* lon=f[5]+1; const char* EW=f[6]+1;
const char* spd=f[7]+1; // "022.4"
int lat5=nmeaDeg5(lat,2); if(*NS=='S') lat5=-lat5;
int lon5=nmeaDeg5(lon,3); if(*EW=='W') lon5=-lon5;
int kn10=toInt3(spd)*10+(spd[3]-'0'); int kmh10=(kn10*1852+500)/1000;
lcd.clear();
lcd.setCursor(0,0); lcdPuts("LAT:"); lcdPrintDec5(lat5); lcd.write(' '); lcd.write(lat5>=0?'N':'S');
lcd.setCursor(0,1); lcdPuts("LON:"); lcdPrintDec5(lon5); lcd.write(' '); lcd.write(lon5>=0?'E':'W');
lcd.setCursor(0,2); lcdPuts("SPD:"); lcdPrintDec1(kmh10); lcdPuts("km/h STAT:"); lcd.write(stat);
}
void showBle(const char* s){
const char* t=strstr(s,"TEMP:"); const char* h=strstr(s,":HUM:"); if(!t||!h) return; t+=5; h+=5;
lcd.clear();
lcd.setCursor(0,0); lcdPuts("Temperature: "); for(const char* q=t; q<h-5 && (q-t)<6; ++q) lcd.write(*q); lcd.write('C');
lcd.setCursor(0,1); lcdPuts("Humidity: "); for(const char* q=h; *q && *q!='\r'&&*q!='\n'&&(q-h)<3; ++q) lcd.write(*q); lcd.write('%');
}
// -------- Генерация кадров в петлю UART --------
void sendGsm(){ static const char* msgs[]={"Hello, this is test.","Data received.","Test message #3."}; static uint8_t i=0;
U.print("GSM:SMS:+79123456789:\""); U.print(msgs[i]); U.print("\"\r\n"); i=(i+1)%3; }
void sendGps(){ U.print("GPS:$GPRMC,125504,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A\r\n"); }
void sendBle(){ U.print("BLE:TEMP:23.5:HUM:65\r\n"); }
// -------- Обработка входящих строк --------
void processLine(char* s){
if (startsWith(s,"GSM:SMS:")) showGsm(s);
else if (strstr(s,"$GPRMC")) showGps(s);
else if (startsWith(s,"BLE:")) showBle(s);
}
// -------- Задачи цикла --------
void handleCLI() {
while (Serial.available()) {
char c = Serial.read();
if (c == '\r' || c == '\n') {
// завершение строки
cli[cliLen] = 0;
// trim пробелы/табуляции
int s = 0, e = cliLen - 1;
while (cli[s] == ' ' || cli[s] == '\t') s++;
while (e >= s && (cli[e] == ' ' || cli[e] == '\t')) e--;
cli[e + 1] = 0;
char *cmd = cli + s;
// to upper
for (char *p = cmd; *p; ++p) if (*p >= 'a' && *p <= 'z') *p += 'A' - 'a';
// диагностика
Serial.print("CMD=["); Serial.print(cmd); Serial.println("]");
// принятие команды (допускаем лишний текст)
if (strstr(cmd, "GSM")) setMode(MODE_GSM);
else if (strstr(cmd, "GPS")) setMode(MODE_GPS);
else if (strstr(cmd, "BLE")) setMode(MODE_BLE);
else if (*cmd) Serial.println("Use: GSM | GPS | BLE");
cliLen = 0;
} else {
if (cliLen < (int)sizeof(cli) - 1) cli[cliLen++] = c;
}
}
}
void handleUART(){
while(U.available()){
char c=U.read(); if(c=='\r') continue;
if(c=='\n'){ rxLine[rxLen]=0; if(rxLen>0) processLine(rxLine); rxLen=0; }
else if(rxLen<(int)sizeof(rxLine)-1) rxLine[rxLen++]=c;
}
}
void maybeSend(){
unsigned long now=millis();
if(modeCur==MODE_GSM && now-tSend>=GSM_PERIOD){ tSend=now; sendGsm(); }
else if(modeCur==MODE_GPS && now-tSend>=GPS_PERIOD){ tSend=now; sendGps(); }
else if(modeCur==MODE_BLE && now-tSend>=BLE_PERIOD){ tSend=now; sendBle(); }
}
// -------- Setup / Loop --------
void setup(){
Serial.begin(115200); // монитор на 115200
U.begin(115200); // USART1 (петля PA9->PA10)
lcd.begin(20,4);
lcd.clear(); lcd.setCursor(0,0); lcdPuts("MODE: IDLE");
Serial.println("Commands: GSM | GPS | BLE");
}
void loop(){
handleCLI();
handleUART();
maybeSend();
}
Loading
st-nucleo-c031c6
st-nucleo-c031c6