大三下华清实训
如下记录在大三下半年结束的课程实训,作为基础知识记录,仅供参考。
知识点:C基础巩固,基本物联网概念,MQTT基础,HAL库入门。
信息:
1、找文件 :
sudo find / -name hq_vm.sh
sudo vim /usr/bin/vmware-config-tools.pl
2、仿真平台
不给看奥
3、笔记
第一天内容
1、基本概念
1、什么是嵌入式
嵌入式 = 硬件 + 软件
- 硬件嵌入:嵌入芯片(让硬件具备运算能力)
- 软件嵌入:嵌入程序或算法(让对硬件的控制更加便捷)
嵌入式是以应用中心,以计算机技术为基础,软硬件结合可裁剪,对功能、体积、功耗和成本有严格要求的计算机系统。
1、主流系统
目前三大主流的操作系统:
- Windows 个人桌面操作系统
- MocOs 个人桌面操作系统
- Linux 小型设备、移动终端(手机、扫地机器人、空气净化器、汽车仪表盘、按摩椅)
Linux特点:
- 免费
- 开源
- 可裁剪
- 好的移植性
2、硬件平台
例子:联发科 四核 A73架构
| |
CPU的个数 ARM公司的Cortex-A73架构
什么是ARM?
- ARM是一家公司
ARM公司是一家知识产权供应商,它与一般半导体公司最大的不同就是不制造芯片且不向用户出售芯片,而是通过转让设计方案,由合作伙伴生产处各具特色的芯片。- ARM是一类处理器的统称
ARM处理器是英国的Acron有限公司设计的低功耗成本的一款RISC微处理器,ARM处理器的内核是统一的,由ARM公司统一提供。- ARM是一种技术
ARM技术具有性能高,成本低,能耗省的特点,在智能手机、平板电脑、嵌入式控制等处理器领域占据主导地位。
ARM处理器的三个系列:
Cortex-A:Application 应用级处理器 [电视、手机、平板、电脑的CPU]
Cortex-R:Realtime 实时处理器 [响应速度快、工业航天、无人驾驶]
Cortex-M:Microcontroller 微控制器 [单片机]
3、常见编程语言
C语言:
主要是做硬件方向编程,是所有高级语言中最接近硬件编程的,想要打造一款智能产品必须和硬件打交道,故不可避免的需要学习C语言,C可以缝合软件和硬件。
C++:
首先可以做游戏开发,C++还搭载强大的Qt图形化库,就业前景比较不错,但Qt库总共就那些函数接口,但日后的职业发展需要转型。
Java:
主要有用来做上层APP或者网页,不推荐本专业学生花费大量时间去学习。因为它偏向纯软,专业不对口且近几年一直再走下坡路。
Python:
主要做AI算法,用户群体主要是研发人员,比如高校的研究生,都回去学习这一门语言。
2、Linux系统简介
常用操作:选中Terminal终端,CtrlShift=为放大字体;Ctrl-为缩小字体;CtrlL清屏;
根目录和家目录的关系:
终端提示,解释:
第二天内容
1、多文件工程
1、 .h 文件
一般包括相应的定义。
编译器将其直接合并到源文件中,
应注意避免重复包含
#ifndef #define #endif
2、 Makefile
随着工程的函数实现源文件越来越多,每次编译时都需要执行gcc main.c a.c b.c ... x.c -o tes t,故需要一个工程化的工具来管理它,这个工具就是Makefile
基本语法:
Makefile三要素格式:
目标 依赖 语句
注意:语句前要有缩进
比如:
包子:面粉 肉馅 酵母 花生油
将面粉 肉馅 酵母 花生油加工成包子的流程
# 语法:
# 目标:依赖
# --------- 语句
# test: main.c a.c
# # gcc main.c a.c -o test
# # 用$^代表所有依赖,用$@代表要的所有目标
# gcc $^ -o $@
test: main.c a.c
gcc $^ -o $@
clean:
rm test
注意:
缺点:假如a.cb.c...z.c名字发生变化,或者增加或删除某些.c函数实现源文件,我们的依赖和语句都要进行修改。
所以Makefile还有个特殊的语法。
$@ 在Makefile语法中代表的是目标
$^ 在Makefile语法中代表的是全部的依赖
常用简写:
test:main.c a.c
gcc $^ -o $@
clean:
rm test
2、项目原理(MQTT)
1、简介
MQTT协议:MessageQueuingTelemetryTransport [消息队列遥测传输协议]
MQTT协议是一种轻量级的,基于发布/订阅(Publish/Subscribe)模式的通信协议,广泛应用于物联网IoT领域。
2、原理
MQTT协议使用了一个中间件MQTT Broker作为消息的中转站,负责接收来自发布者的消息并将其推送给订阅者。
发布者Publisher将消息发布到一个特定的主题Topic上,订阅者Subscriber通过订阅该主题Topic来接收主题上的消息。
举例:
抖音作为mqtt 服务器,
发布者(同学的抖音)和订阅者(老师的抖音)都是客户端。
注意:每个客户端都可以作为发布者和订阅者,这里举例用一种。
MQTT协议使用了一个MQTT服务器作为消息的中转站,负责接收来自发布者的消息并将其推送给订阅者。
发布者将消息发布到一个特定的主题上:同学将短视频发布到特定的抖音号上。
订阅者通过订阅该主题来接收消息:老师通过订阅抖音号来接收同学发布的短视频。
抖音服务器作为短视频中转站,负责接收同学发布的短视频,然后将其推送给老师。
客户端既可以是发布者也可以是订阅者。
用户既可以是博主也可以是粉丝。
3、用法
代码举例:
------------------------------------------------
int mqtt_init()
功能:
初始化MQTT——连接
------------------------------------------------
int mqtt_subscribe(const char *topic)
功能:
订阅发布者发布的主题,以收到发布者发布的消息
参数:
const char *topic 虚拟仿真平台的发布主题
------------------------------------------------
int mqtt_publish(const char *topic, char *msg)
功能:
向订阅者订阅的主题发布cJSON格式的控制指令
参数:
const char *topic 虚拟仿真平台的订阅主题
char *msg 要发布的消息正文(控制指令)
------------------------------------------------
4、mqtt.fx软件使用
解释:
fx作为接收报文者,虚拟节点作为发送报文者,fx需要知道节点对外发布的主题,才能向服务器索要该部分数据。
区别于下文代码案例。
数据格式为json:
{"soiltem":20.1,"soilhum":50.1,"id":0}
{"alarm":false,"id":0}
{"irrigated":false,"id":0}{"alarm":true,"id":0}
{"irrigated":true,"id":0}
5、linux配网
虚拟机使用NAT模式上网,作为宿主机的子机器,类似主机为路由根,其网络内虚拟机作为ip节点。
因此,可以ping通宿主机。
6、paho.mqtt库移植
paho.mqtt.c 是Eclipse编写的开源mqtt c库,支持Posix标准操作系统(如Linux,Android,Mac)和windows操作系统。
Paho MQTT C客户端支持全部MQTT协议客户端特性,它使用ANSI标准C编写。
3、项目开发
内容:虚拟机客户端与虚拟节点客户端通信,华清平台作为服务器代理。
1、获取虚拟节点客户端ID
2、main代码
#include "mqtt.h"
#include "cJSON.h"
int main(int argc, char const *argv[])
{
// 1.连接服务器
mqtt_init();
// 2.订阅平台主题,获得数据串
// 通过目标节点的发布主题,才能得到其发布的内容
mqtt_subscribe("1688456069723/AIOTSIM2APP");
// 3.定义变量接收到存储解析的数据
float SoilHum = 0;
// 4.循环获取数据,下发控制指令,打印湿度值
while (1)
{
sleep(3); // 间隔3s
// 从json解析:{ "soiltem":20.1, "soilhum" :50.1, "id":0} ==> 50
SoilHum = get_virtual_env();
// 得知目标节点的订阅主题,才能向其发布内容
// 理解:某节点想得到什么,则暴露自身的需求的主题,其他节点通过该主题,才可发给它
// int mqtt_publish(const char *topic, char *msg)
if (SoilHum > 20)
{
mqtt_publish("1688456069723/APP2AIOTSIM", "{\"irrigated\":,false,\"id\":0}");
mqtt_publish("1688456069723/APP2AIOTSIM", "{\"alarm\":,false,\"id\":0}");
printf("关闭喷林和警报\n");
}
else if (SoilHum < 10)
{
mqtt_publish("1688456069723/APP2AIOTSIM", "{\"irrigated\":,true,\"id\":0}");
mqtt_publish("1688456069723/APP2AIOTSIM", "{\"alarm\":,true,\"id\":0}");
printf("打开喷林和警报\n");
}
printf("当前湿度:%.2f\n", SoilHum);
}
return 0;
}
第三天内容
1、开发环境及工具介绍
Keil 单片机集成开发环境
集成开发环境:就是把代码编写、编译、调试和下载的功能全部集中到一个软件中。
STM32CubeMX ST公司提供的一款快速开发STM32的一款工程搭建软件。
stm32介绍:
ST:意法半导体(一家公司)
M:微型处理器
32:32位
STM32CubeMX为了方便开发人员进行开发,可以在里面进行相应的配置,配置好之后直接生成工程。
ST公司一系列产品都有各种型号供开发人员选择,选择之后配置好相关引脚,就可以直接生成工程。
工程包括启动文件、各种设备的驱动文件、库文件。
stlink介绍:
STLink是一种用于在STM32上进行编程和调试的工具,支持多种编程接口,主要功能如下:
- 代码下载:可以将在Keil上编写的代码下载到STM32开发板的内部内存或者外部存储器上,以便于实现嵌入式系统的功能。
- 调试支持
- 系统复位
- 目标设备识别
- 串口通信
2、基本概念介绍
1、GPIO
GPIO:General-purpose Input/Output 通用型输入输出
如何点亮一盏灯?:灯亮——电流——电势差
输出就是单片机通过输出高低电平来控制设备的工作。
输入就是采集设备发送给单片机的信号。
1、代码
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
功能:读取引脚电平状态
参数:
端口号
引脚号
返回值
引脚高低电平 0 / 1
以土壤湿度传感器为例子,采集数字输出:
湿度低于设定值时,DO 输出高电平,高于设定值时,DO 输出低电平;
if (0 == HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4))
{
HAL_Delay(10);
if (0 == HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4))
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_PIN_RESET);
}
if (1 == HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4))
{
HAL_Delay(10);
if (1 == HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4))
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_PIN_SET);
}
2、步骤
**注意:**代码放入用户代码区
- 先选择成 推挽输出
- 配置
3. 勾选生成多文件工程
- 生成代码
2、串口通信
**通信的基本概念:**两个通信对象,一个发送方 一个接收方;也甚至可以都作为发送及接收方。
在不同时间不同地点不同媒介如何保证实现通信呢?我知道你,你知道我。
3、通信属性划分
- 有无时钟源
- 通信方式
- 传输方向
1、有无时钟源
**同步通信:**你我之间共有一块表(有时钟线)
**异步通信:**各自各自的表,会涉及到通信双方的表时刻不一致,那么就不能约定某个时间去进行通信,而是约定每隔一个固定的时间,双方通信一次,故需要约定通信速度。因此,为了保证数据的准确性,通信双方要约定好通信速度
**通信速度:**单位时间内发送或接收的数据位数
**波特率:**一秒发送多少个bit位信息 bit/s bps 115200bps
2、通信方式
**串行通信:**指同一时刻只能收或发一个bit位信息,因此只需要一根数据线即可。
优点:占用的引脚资源少
缺点:通信效率低
**并行通信:**同一时刻可以收或发多个bit位信息,因此需要多跟数据线才行。
优点:通信效率高
缺点:占用引脚资源多
3、传输方向
判定一方是属于发送方还是接收方,一定要考虑实际情况,不要理所当然。
**单工:**只能作为发送或接收设备,发送方发送数据,接收放接收数据(收音机)
**半双工:**可以作为发送设备也可以作为接收设备,但是同一时刻只能接收或者发送,不能同时收发(对讲机)
**全双工:**同一时刻既可以接收也可以发送(打电话)
4、串口发送实验
UART是一种异步的串行全双通的通信接口。
代码:
// 串口
HAL_UART_Transmit(&huart1, "hello", 5, 1000);
HAL_Delay(1000);
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, \
const uint8_t *pData, \
uint16_t Size, \
uint32_t Timeout)
功能:
串口发送
参数:
UART_HandleTypeDef *huart 句柄 &huart1
const uint8_t *pData 要发送数据的首地址 "Hello"
uint16_t Size 要发送数据的长度 5
uint32_t Timeout 超时时间 1000
步骤:
选择好要配置的内容
5、串口接收实验
Tips:
需要使用到string函数族的strcmp字符串比较函数,如果控制指令不能准确控制设备做出动作则需要用到memset函数。
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, \
uint8_t *pData, \
uint16_t Size, \
uint32_t Timeout)
功能:串口接收
参数:
UART_HandleTypeDef *huart 句柄 &huart1
uint8_t *pData 接收到的数据的存放地址
uint16_t Size 接收的数据长度
uint32_t Timeout 超时时间 1000
6、C库输入输出重定向
重定向:重新规定输入的方向,就是重新规定一下数据该从哪里拿。
原本scanf是从标准输入中读取数据,现在重定向一下让其从串口中拿数据,
重新规定输出的方向,就是重新规定一下数据该往哪里放。
原本printf是往标准输出上输出内容,现在重定向一下让其将数据输出到串口上。
1、输出重定向
printf使用标准C库里面fputc,只需要重写fputc(将输出方向重定向到串口)即可将要打印的内容通过串口线进行输出。
添加头文件:
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
输出重定向:
/* USER CODE BEGIN 4 */
int fputc(int ch, FILE * f)
{
// 等待发送寄存器为空,ISR的第七位为1说明发送寄存器为空,则应该跳出循环向下执行。
while (!(USART1->ISR & (1<<7)));
// 往串口中写实际上是往串口的发送寄存器中写
// 将要发送的数据赋值给串口中的发送寄存器
USART1->TDR = ch;
return ch;
}
/* USER CODE END 4 */
7、HAL ADC转换步骤
- 打开ADC HAL_ADC_Start
- 等待ADC转化 HAL_ADC_PllForConversion
- 获取ADC转化出来的值 HAL_ADC_GetValue
- 关闭ADC HAL_ADC_Stop
1、土壤湿度adc采集案例
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
/* USER CODE BEGIN 2 */
uint32_t HumValue;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_ADC_Start(&hadc);
HAL_ADC_PollForConversion(&hadc, 100);
HumValue = HAL_ADC_GetValue(&hadc);
HAL_ADC_Stop(&hadc);
printf("%d", HumValue);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
2、继电器
8、项目
当土壤湿度高于阈值时打开水泵,低于阈值时关闭水泵,并每隔一秒将数据发送到串口调试助手上
采集到的数据和土壤湿度成反比。
实现自动灌溉功能。
1、步骤