X
首页
技术
模拟电子
单片机
半导体
电源管理
嵌入式
传感器
最能打国产芯
应用
汽车电子
工业控制
家用电子
手机便携
安防电子
医疗电子
网络通信
测试测量
物联网
最能打国产芯
大学堂
首页
直播
专题
TI 培训
论坛
汽车电子
国产芯片
电机驱动控制
电源技术
单片机
模拟电子
PCB设计
电子竞赛
DIY/开源
嵌入式系统
医疗电子
颁奖专区
【厂商专区】
【电子技术】
【创意与实践】
【行业应用】
【休息一下】
最能打国产芯
活动中心
直播
发现活动
颁奖区
电子头条
参考设计
下载中心
分类资源
文集
排行榜
电路图
Datasheet
最能打国产芯
传感器
[活动] 【DFRobot 云雀气象仪】学习笔记02(自动化获取数据并保存到本地数据库)
qzc0927
2023-11-1 23:37
楼主
## 5:本地数据库保存 数据在实际工作中应用非常广泛,数据库的产品也比较多,oracle、DB2、SQL2000、mySQL;基于嵌入式linux的数据库主要有SQLite, Firebird, Berkeley DB, eXtremeDB。这里我们主要采用sqlite3数据库,来做本地数据存储; ![image-20231101225100427](https://boreyun.oss-cn-shanghai.aliyuncs.com/image-20231101225100427.png) 这里我们首先创建一个Weather天气的数据表,表中包含温度,湿度,海拔,起亚,电压,电池,风向,风速,以及日期的数据字段,ID代表数据序列号,为自增字段。 ## 6:上位机编写 我们编写上位机来自动接收数据,并将接收到的数据放入本地数据库,也就是sqlite3数据库下。上位机实用C#开发,使用visualstudio2019主要分为以下2个步骤: 1. 数据的获取 2. 连接数据库并保存 ### 6.1:数据的获取 数据的获取采用串口通讯来实现,首先进行串口的开关,然后实现串口的收发,最后添加定时器,实现数据的自动化接收。 首先事串口的打开和关闭,我们使用串口组件,和按钮以及多选框来实现串口的打开和关闭。组件设计截图如下: ![image-20231101230018858](https://boreyun.oss-cn-shanghai.aliyuncs.com/image-20231101230018858.png) 串口打开和关闭的代码如下: ```C# private void btnSerialOpen_Click(object sender, EventArgs e) { if (serialPort.IsOpen) { //System.Windows.Forms.Application.DoEvents(); //serialPort.Dispose(); serialPort.Close(); cmbSerialNo.Enabled = true;//关闭串口后可以选择串口号和波特率 cmbBand.Enabled = true; } else { /*获取串口名字*/ serialPort.PortName = cmbSerialNo.Text; /*获取波特率信息,并转化为int类型*/ serialPort.BaudRate = Convert.ToInt32(cmbBand.Text, 10); try { serialPort.Open(); //打开串口 serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived); //数据接收事件的方法 cmbBand.Enabled = false;//关闭使能,无法选择 cmbSerialNo.Enabled = false; } catch { MessageBox.Show("串口打开失败!"); return; } } //设置串口按钮状态 btnSerialOpen.Text = serialPort.IsOpen ? "关闭" : "打开"; lblSerialState.ForeColor = serialPort.IsOpen ? Color.Green : Color.Red; toolStripStatusLabel1.Text = serialPort.IsOpen ? "状态:"+"串口已打开" : "状态:" + "串口已关闭"; } ``` 其次,对于串口的收发处理,使用功能函数serialPort_DataReceived来实现,具体代码为: ```C# private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { SerialPort serialPort = (SerialPort)sender; //将当前线程挂起50ms,缓存数据,让数据接收完毕 System.Threading.Thread.Sleep(100); // 读取接收缓冲区中的数据 int bytesToRead = serialPort.BytesToRead; //如果有数据 if (bytesToRead>0) { byte[] buffer = new byte[bytesToRead]; serialPort.Read(buffer, 0, bytesToRead); // 添加数据到接收缓存区 receiveBuffer.AddRange(buffer); //显示接受到的数据 Invoke(new Action(() => { rtxRecvBuff.Text += System.Text.Encoding.UTF8.GetString(receiveBuffer.ToArray()); })); // 处理接收缓存区中的数据 ProcessReceivedData(); } } ``` 最后的添加定时器,进行自动化接收天气数据,为了有效获取数据,我们分别读取各个传感器的数据信息,使用不同的串口指令,利用状态机的形式,配合定时器,循环得到各个传感器的数据,具体代码为: ```C# private void weatherTimer_Tick(object sender, EventArgs e) { switch (sensorState) //写完枚举后敲回车将自动补完枚举类型 { case OptCode.Init: timeCount++; if (timeCount == 1) //延时2S*10=20S { timeCount = 0; Weather_SQL_Insert(); sensorState = OptCode.Temp; } break; case OptCode.Temp: GetTemp_Cmd_Send(); break; case OptCode.Humi: GetHumi_Cmd_Send(); break; case OptCode.WindSpeed: GetWindSpeed_Cmd_Send(); break; case OptCode.WindDirection: GetWindDirection_Cmd_Send(); break; case OptCode.Altitude: GetAltitude_Cmd_Send(); break; case OptCode.Pressure: GetPressure_Cmd_Send(); break; default: break; } } ``` ### 6.2:连接数据库并保存 首先创建sql数据库类,方便数据库操作,具体实现代码如下: ```C# using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.SQLite; namespace SerialPortHelper { class SqLiteHelper { ///
/// 数据库连接定义 ///
private SQLiteConnection dbConnection; ///
/// SQL命令定义 ///
private SQLiteCommand dbCommand; ///
/// 数据读取定义 ///
private SQLiteDataReader dataReader; ///
/// 构造函数 ///
///
连接SQLite库字符串 public SqLiteHelper(string connectionString) { try { dbConnection = new SQLiteConnection(connectionString); dbConnection.Open(); } catch (Exception e) { Log(e.ToString()); } } ///
/// 执行SQL命令 ///
///
The query.
///
SQL命令字符串 public SQLiteDataReader ExecuteQuery(string queryString) { try { dbCommand = dbConnection.CreateCommand(); dbCommand.CommandText = queryString; dataReader = dbCommand.ExecuteReader(); } catch (Exception e) { Log(e.Message); } return dataReader; } ///
/// 关闭数据库连接 ///
public void CloseConnection() { //销毁Commend if (dbCommand != null) { dbCommand.Cancel(); } dbCommand = null; //销毁Reader if (dataReader != null) { dataReader.Close(); } dataReader = null; //销毁Connection if (dbConnection != null) { dbConnection.Close(); } dbConnection = null; } ///
/// 读取整张数据表 ///
///
The full table.
///
数据表名称 public SQLiteDataReader ReadFullTable(string tableName) { string queryString = "SELECT * FROM " + tableName; return ExecuteQuery(queryString); } ///
/// 向指定数据表中插入数据 ///
///
The values.
///
数据表名称 ///
插入的数值 public SQLiteDataReader InsertValues(string tableName, string[] values) { //获取数据表中字段数目 int fieldCount = ReadFullTable(tableName).FieldCount; //当插入的数据长度不等于字段数目时引发异常 if (values.Length != fieldCount) { throw new SQLiteException("values.Length!=fieldCount"); } string queryString = "INSERT INTO " + tableName + " VALUES (" + "'" + values[0] + "'"; for (int i = 1; i < values.Length; i++) { queryString += ", " + "'" + values[i] + "'"; } queryString += " )"; return ExecuteQuery(queryString); } ///
/// 更新指定数据表内的数据 ///
///
The values.
///
数据表名称 ///
字段名 ///
字段名对应的数据 ///
关键字 ///
关键字对应的值 ///
运算符:=,<,>,...,默认“=” public SQLiteDataReader UpdateValues(string tableName, string[] colNames, string[] colValues, string key, string value, string operation = "=") { //当字段名称和字段数值不对应时引发异常 if (colNames.Length != colValues.Length) { throw new SQLiteException("colNames.Length!=colValues.Length"); } string queryString = "UPDATE " + tableName + " SET " + colNames[0] + "=" + "'" + colValues[0] + "'"; for (int i = 1; i < colValues.Length; i++) { queryString += ", " + colNames[i] + "=" + "'" + colValues[i] + "'"; } queryString += " WHERE " + key + operation + "'" + value + "'"; return ExecuteQuery(queryString); } ///
/// 删除指定数据表内的数据 ///
///
The values.
///
数据表名称 ///
字段名 ///
字段名对应的数据 public SQLiteDataReader DeleteValuesOR(string tableName, string[] colNames, string[] colValues, string[] operations) { //当字段名称和字段数值不对应时引发异常 if (colNames.Length != colValues.Length || operations.Length != colNames.Length || operations.Length != colValues.Length) { throw new SQLiteException("colNames.Length!=colValues.Length || operations.Length!=colNames.Length || operations.Length!=colValues.Length"); } string queryString = "DELETE FROM " + tableName + " WHERE " + colNames[0] + operations[0] + "'" + colValues[0] + "'"; for (int i = 1; i < colValues.Length; i++) { queryString += "OR " + colNames[i] + operations[0] + "'" + colValues[i] + "'"; } return ExecuteQuery(queryString); } ///
/// 删除指定数据表内的数据 ///
///
The values.
///
数据表名称 ///
字段名 ///
字段名对应的数据 public SQLiteDataReader DeleteValuesAND(string tableName, string[] colNames, string[] colValues, string[] operations) { //当字段名称和字段数值不对应时引发异常 if (colNames.Length != colValues.Length || operations.Length != colNames.Length || operations.Length != colValues.Length) { throw new SQLiteException("colNames.Length!=colValues.Length || operations.Length!=colNames.Length || operations.Length!=colValues.Length"); } string queryString = "DELETE FROM " + tableName + " WHERE " + colNames[0] + operations[0] + "'" + colValues[0] + "'"; for (int i = 1; i < colValues.Length; i++) { queryString += " AND " + colNames[i] + operations[i] + "'" + colValues[i] + "'"; } return ExecuteQuery(queryString); } ///
/// 创建数据表 ///
+ ///
The table.
///
数据表名 ///
字段名 ///
字段名类型 public SQLiteDataReader CreateTable(string tableName, string[] colNames, string[] colTypes) { string queryString = "CREATE TABLE IF NOT EXISTS " + tableName + "( " + colNames[0] + " " + colTypes[0]; for (int i = 1; i < colNames.Length; i++) { queryString += ", " + colNames[i] + " " + colTypes[i]; } queryString += ") "; return ExecuteQuery(queryString); } ///
/// Reads the table. ///
///
The table.
///
Table name. ///
Items. ///
Col names. ///
Operations. ///
Col values. public SQLiteDataReader ReadTable(string tableName, string[] items, string[] colNames, string[] operations, string[] colValues) { string queryString = "SELECT " + items[0]; for (int i = 1; i < items.Length; i++) { queryString += ", " + items[i]; } queryString += " FROM " + tableName + " WHERE " + colNames[0] + " " + operations[0] + " " + colValues[0]; for (int i = 0; i < colNames.Length; i++) { queryString += " AND " + colNames[i] + " " + operations[i] + " " + colValues[0] + " "; } return ExecuteQuery(queryString); } ///
/// 本类log ///
///
static void Log(string s) { Console.WriteLine("class SqLiteHelper:::" + s); } } } ``` 数据信息的插入,具体的SQL语句可以参考菜鸟教程,里面有项目说明sql的各种操作。 [SQLite 教程 | 菜鸟教程 (runoob.com)](https://www.runoob.com/sqlite/sqlite-tutorial.html) 这里我们就不细说,直接上关键的数据库连接代码。 ```C# public void Weather_SQL_Insert() { try { //连接数据库 Global.sqlConn = new SqLiteHelper("data source=SerialPortHelper.db"); string insertString = "INSERT INTO Weather(Temp,Humi,WindSpeed,WindDirection,Altitude,Pressure,Date)VALUES(" + tempStr + " ," + humiStr + ","+ speedStr + ","+ dirStr + ","+ altiStr + ","+ pressStr + ","+ DateTime.Now.ToLocalTime().ToString("yyyyMMddHHmmss") + ")"; Global.sqlConn.ExecuteQuery(insertString); Global.sqlConn.CloseConnection(); } catch (Exception ex) { MessageBox.Show(ex.Message); } finally { Global.sqlConn.CloseConnection(); } } ``` 最后打开的数据库工具,查看数据是否更新。 ![image-20231101232420951](https://boreyun.oss-cn-shanghai.aliyuncs.com/image-20231101232420951.png) 自此,数据保存成功。 具体演示视频如下: https://www.bilibili.com/video/BV1SH4y1z7ys/
点赞
回复评论 (1)
沙发
lugl4313820
楼主的技术牛呀,软件硬件通吃,佩服佩服!
点赞
2023-11-2 06:56
最新活动
有奖直播报名中!抢占工业4.1先机 文晔科技日等你来!
2024 瑞萨电子MCU/MPU工业技术研讨会——深圳、上海站, 火热报名中
罗姆有奖直播 | 重点解析双极型晶体管的实用选型方法和使用方法
STM32N6终于要发布了,ST首款带有NPU的MCU到底怎么样,欢迎小伙们来STM32全球线上峰会寻找答案!
免费下载 | 安森美电动汽车充电白皮书,看碳化硅如何缓解“里程焦虑”!
是德科技有奖直播 | 应对未来高速算力芯片的设计与测试挑战
随便看看
NVR的核心价值是什么
搭建zigbee出现的问题
除了超声波测距你们还有什么方法测呢
超级电容器,备用电源最佳的解决方案?
MIPS寄存器约定
2440 Buffer_preview_info_update 问题
stm8l在STVD软仿真时Memory的值全是0xFF
大家一起学CC3200 Wi-Fi MCU
AVX 的电容问题。。。
场效应管
欢迎大家光临器材资料库
Virtex-6 FPGA User Guide
诺基亚暗码查寻
公司项目做的差不多了,全部被认证打下来了
FPGA开发齐全
体验了一把Vishay电工游戏,差点中奖
推荐下dsp 的书籍
KiCad 生产文件生成器
qiuMSP430单片机100引脚SCH和PCB封装下载
【奇趣51DIY】之1——LC测量小工具(03月01日-04月10日)
电子工程世界版权所有
京B2-20211791
京ICP备10001474号-1
京公网安备 11010802033920号
回复
写回复
收藏
回复