嵌入式适合哪些人学
本专业的学生
主要是电子类的学生,比如电子信息工程、通信工程、自动化、机械电子工程、仪器仪表等专业的学生,本人就是电子信息工程专业。计算机科学、软件工程之类的也可以学,但是这些偏纯软件方向,可能去BAT之类的是更好的选择。
纯软想转行的工程师
现在互联网看似接近饱和,移动互联网带来的春天已经过去,头部APP结束了神仙打架的斗争,移动互联网已经渗透到生活的角角落落,打个车,买个菜都要用个APP,纯软找工作没有之前那么吃香了。反而是电动汽车、智能家电、无人机、机器人等大放异彩,开辟出了新的千万亿级别的市场。纯软有着软件开发的先天优势,加上现在的嵌入式系统本身好多都已经基于linux、andriod等操作系统平台,越来越脱离底层硬件,偏向纯软件开发,纯软件工程师转行也不失为一个好选择。例如下图中基于linux的核心板,已经完成了最新linux 5.4内核版本操作系统的驱动支持,软件开发完善,并经过长时间老化测试、高低温测试、通断电测试,测试后性能稳定,且核心板的外形小巧,尺寸仅为37mm*39mm,采用邮票孔封装焊接到底板,稳固不易松动,可适应于工程机械产品严苛的工业环境要求。核心板实现OTG,TF卡多种烧写方式,预留140个引脚的外扩接口,其包含了丰富的外设资源,便于灵活开发应用。
敲黑板:真的只要写应用层就可以了!!!
图1 基于linux核心板的嵌入式开发
电子爱好者
如今知识传播的方式和速度都有了质的飞跃,各种电子模组层出不穷,不是科班出身,也能玩转嵌入式。嵌入式开发越来越像搭积木,想要语音识别、人脸识别、图像显示、联网通信都有相应的模组可以购买,无需研究模数转换、信号处理、电磁场电磁波等等高深学科。甚至自己的主控芯片都可以不了解,Arduino对芯片底层进行了封装,MicroPython还支持使用Python语言操作硬件例如OpenMV。直接像写纯软件一样调用函数接口,就可以操作硬件电路。什么晦涩难懂的寄存器、硬件驱动统统不用管,也能开发出很牛的作品。
图2 基于Python开发OpenMV
嵌入式学什么
如果只是爱好者,我建议就学arduino就够了,十几块钱买个esp8266或者二三十买个esp32就可以玩起来了,教程特别多,还可以连接互联网,我不在这里赘述,我自己后面也会分享基于arduino的设计。对了arduino是一个组织,不是一个单片机型号,他们把常见的单片机的底层进行了统一的封装也就是硬件抽象,比如stm32、avr、esp8266等等,在不同型号的的单片机上开发感觉都一样,不用关心底层。缺点不能直接和硬件打交道,所以没有那么灵活,实时性也差一点,建议本专业的还是不能止步于此。arduino是基于c++的,当然只是使用的话用c那部分内容就够了,没必要自己造一个对象出来。嵌入式的话c是肯定要学的,会c++就更好了。这里涉及到面向对象还是面向过程编程的知识,暂时按下不表吧。
如果是本专业的学生,我觉得可以从stm32起步,因为资源实在是太多了,硬件驱动都可以用STM32CUBEMX自动生成了。
图3 基于STM32CUBEMX生成硬件驱动
还有就是学好专业课,c语言、微机原理、数字电路、模拟电路、信号与系统、控制工程、电磁场与电磁波,相信我以后多多少少都能用上些。就算是不知道有啥用,光想卷高分考研进大厂也必须学,嵌入式行业大厂和小厂就不是一个职业感受。进阶方向的话还是要向ZYNQ(ARM+FPGA)、实时操作系统、嵌入式AI、控制算法等有难度的挣钱多的方向。
Talk is cheap Show me the CODE!
8051单片机串口收发
以下是一个基于标准8051单片机(假设使用11.0592MHz晶振)通过软件模拟实现接近115200波特率收发的简单示例。请注意,由于标准8051的定时器限制,直接实现115200波特率可能不太精确,但我们可以尽量接近。
首先,我们需要配置单片机的串口(UART)为模式1(8位可变波特率,无奇偶校验位,1个停止位)。然后,使用定时器1来生成接近的波特率。
#include <reg51.h>
#define FOSC 11059200UL // 晶振频率
#define BAUDRATE 115200 // 目标波特率
// 计算定时器重装值(这里为了简化,直接给出一个接近的值,可能需要调整以达到最佳效果)
#define TH1_VAL ((65536 - (FOSC / 12 / 32) / BAUDRATE) >> 8)
#define TL1_VAL ((65536 - (FOSC / 12 / 32) / BAUDRATE) & 0xFF)
void UART_Init() {
TMOD &= 0xF0; // 清除定时器1模式位
TMOD |= 0x20; // 设置定时器1为模式2(8位自动重装)
TH1 = TH1_VAL; // 设置定时器重装值
TL1 = TL1_VAL;
TR1 = 1; // 启动定时器1
SCON = 0x50; // 设置为模式1, 允许接收
PCON &= 0x7F; // SMOD = 0 (不加倍波特率)
}
void UART_SendByte(unsigned char byte) {
SBUF = byte; // 写入数据到SBUF
while (!TI); // 等待发送完成
TI = 0; // 清除发送完成标志
}
unsigned char UART_ReceiveByte(void) {
while (!RI); // 等待接收完成
RI = 0; // 清除接收完成标志
return SBUF; // 返回接收到的数据
}
void main() {
UART_Init(); // 初始化UART
while (1) {
// 发送数据
UART_SendByte('H');
UART_SendByte('e');
UART_SendByte('l');
UART_SendByte('l');
UART_SendByte('o');
// 延时或其他操作
// 接收数据(这里只是简单示例,实际应用中你可能需要处理接收到的数据)
// unsigned char receivedByte = UART_ReceiveByte();
// ...
}
}
Arduino上实现串口收发
在Arduino上实现115200波特率的UART(通用异步收发传输器)通信相对简单,因为Arduino的Serial库已经为你处理了大部分底层的配置工作。Arduino的Serial库默认就支持多种波特率,包括115200。
以下是一个简单的示例,展示了如何在Arduino上设置115200波特率进行数据的发送和接收。
发送数据
首先,你需要在setup()函数中设置Serial通信的波特率。然后,在loop()函数中,你可以使用Serial.write()或Serial.println()等函数来发送数据。
void setup() {
// 设置串口波特率为115200
Serial.begin(115200);
}
void loop() {
// 发送字符串
Serial.println("Hello, 115200 baud!");
// 发送单个字节
Serial.write(0xAA);
// 等待一段时间,避免发送过快
delay(1000);
}
接收数据
在Arduino中接收数据同样简单。你可以使用Serial.available()函数来检查是否有数据可读,然后使用Serial.read()或Serial.readString()等函数来读取数据。
void setup() {
// 设置串口波特率为115200
Serial.begin(115200);
}
void loop() {
// 检查是否有数据可读
if (Serial.available() > 0) {
// 读取一个字节
char incomingByte = Serial.read();
// 发送接收到的字节回去,作为回显
Serial.write(incomingByte);
// 或者,如果你希望读取一个字符串直到遇到换行符
/*
String data = Serial.readStringUntil('\n');
Serial.println(data);
*/
}
}
STM32的HAL(硬件抽象层)库实现串口收发
STM32的HAL(硬件抽象层)库为开发者提供了一种高级的、易于使用的接口来配置和控制STM32微控制器的各种外设,包括UART(通用异步收发传输器)通信。当你想通过STM32的UART接口以115200波特率发送和接收数据时,你可以使用HAL库中的UART相关函数来实现。
以下是一个基于STM32 HAL库的简单示例,展示了如何配置UART以115200波特率进行数据的发送和接收。请注意,这个示例假设你正在使用STM32CubeMX来生成初始化代码,或者你已经手动配置了所需的时钟和GPIO引脚。
- 配置UART
首先,你需要配置UART的参数,包括波特率、数据位、停止位和奇偶校验位。这通常是通过调用HAL_UART_Init()函数并传递一个包含UART配置参数的UART_InitTypeDef结构体来完成的。
示例代码
以下是一个简化的示例,展示了如何在STM32项目中配置UART并发送/接收数据。
#include "stm32f1xx_hal.h" // 注意:根据你的STM32系列选择合适的头文件
UART_HandleTypeDef huart1;
// UART配置结构体
UART_InitTypeDef UART_InitStruct = {0};
// 假设你已经有了GPIO和时钟配置的代码
void SystemClock_Config(void); // 时钟配置函数,通常由STM32CubeMX生成
static void MX_GPIO_Init(void); // GPIO初始化函数,通常由STM32CubeMX生成
static void MX_USART1_UART_Init(void); // UART初始化函数
int main(void)
{
HAL_Init(); // 初始化HAL库
SystemClock_Config(); // 配置系统时钟
MX_GPIO_Init(); // 初始化GPIO
MX_USART1_UART_Init(); // 初始化UART
while (1)
{
// 发送数据
HAL_UART_Transmit(&huart1, (uint8_t*)"Hello, 115200 baud!\r\n", 21, HAL_MAX_DELAY);
// 等待一段时间,以便可以观察到发送的数据
HAL_Delay(1000);
// 接收数据(这里只是示例,实际使用时需要处理接收到的数据)
// 注意:这里没有实现完整的接收逻辑,只是展示了如何调用接收函数
// 你可能需要在一个循环中检查UART接收缓冲区,或者使用中断/DMA来处理接收到的数据
}
}
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1; // 指定USART实例
huart1.Init.BaudRate = 115200; // 设置波特率
huart1.Init.WordLength = UART_WORDLENGTH_8B; // 设置数据位为8位
huart1.Init.StopBits = UART_STOPBITS_1; // 设置停止位为1位
huart1.Init.Parity = UART_PARITY_NONE; // 设置无奇偶校验位
huart1.Init.Mode = UART_MODE_TX_RX; // 设置UART为发送和接收模式
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; // 设置无硬件流控制
huart1.Init.OverSampling = UART_OVERSAMPLING_16; // 设置过采样为16
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler(); // 错误处理函数
}
}
// 错误处理函数(简单示例,实际项目中可能需要更复杂的处理)
void Error_Handler(void)
{
// 用户可以添加错误处理代码,例如重置MCU
__disable_irq();
while (1)
{
}
}
// 请确保你有SystemClock_Config()和MX_GPIO_Init()的实现,这些函数通常由STM32CubeMX生成
嵌入式怎么学
我不想上来就列一大堆书单、给一串视频链接,这些看着都很枯燥乏味。没有及时的正面反馈,人是很难坚持一件事情的。我学的很多东西都是项目牵引,找一个目标去学,比盲目看视频看书有意思多了。找一个能够的着的目标,把一个大目标分解下去,成了多个小目标,然后各个击破。带着目的去学,用到什么学什么,不用的就先不看,这样下来不用几个项目练手,你就基本掌握了嵌入式开发了。
比如你想做一个测量室内甲醛浓度的设备,那就需要一个单片机,一个甲醛传感器,一个显示器,这些就够了,大概会应用到串口,gpio,i2c,spi之类的,根据传感器和显示器的类型不同选择。最简单的串口传感器搭配上数码管显示就行。去看串口传感器资料,看看通信协议,去看看数码管的资料了解什么是段码和位码。去看看怎么新建一个工程,怎么点亮数码管,怎么实现串口收发数据。慢慢的学习兴趣就来了,就能坚持下来了,也有可能就放弃了,毕竟不是人人都喜欢不停的看手册。
然后再提高,传感器数据能不能送到服务器上,数码管显示太low了能不能换led屏幕,能不能画块板子把这些电子零件都装起来,能不能做到低功耗运行不用外接电源一个电池就能用半年,慢慢向产品考虑。因为前期已经付出了,后面改进的动力会让你不停的去学习。所以后面我会分享一两个小而精的项目,讲细一点基础一点,重点是怎么查资料看手册,相当于手把手教吧,为了不掏钱,我会基于protues仿真运行方便大家重复,这个过程不会太久,毕竟搞过的东西再搞就没什么意思了。我还是想搞一些有难度的,比如RT-Thread实时操作系统,嵌入式AI等等,也会分享一些工作中踩到的很底层的坑。