手把手教你学单片机进阶-框架篇(上)
如何学习单片机?单片机编程入门教程

如何学习单片机?单片机编程入门教程单片机学习起来其实不难,反而是一件比较好玩的事情,之所以新手感觉比较难是由于不知道该怎么入手,从哪里开头学起。
单片机的学习无外乎两便利.一,电路。
二,编程语言。
先说电路,说到电路不得不提三本书。
模电,数电,电路。
可以说这三本书是学习电路的必经之路,学好这些,即使你不学单片机也可以找到一份薪资满足的工作。
当然现在大公司工作都是分工明确的,做电路的就做电路。
单片机编程的就做编程。
不过能进大公司的还是少数。
大部分小公司要求你全能,也就是说一个项目你要从芯片的选型,到外围电路的搭建,最终I/O口的定义,程序的编译调试,最终PCB 板的制作,焊接,调试等等,你都要把握。
当然你的工资也是客观的。
我的意思是学习单片机最好是要学习电路。
接下来学编程语言,单片机的编程语言是结构化的C语言。
C语言的学习也不是那么简单的,至少指针就够你模糊一段时间的。
学习C你可以先系统的学习一段时间,做一些练习,不用焦急去将它应用到单片机上。
学习单片机需要动手,不是照着课本去死记硬背。
所以学习单片机的第一个概念:确定好所学习的单片机详细型号。
比如说,你要学习51单片机,你所确定的型号是STC89C52,这款单片机虽然比较老了,但是依旧具有学习价值,DIP40封装的STC89C52单片机如下图所示:或者你选择STM32单片机学习,比如STM32F103C8T6,LQFP48封装的单片机如下图所示:确定了单片机的详细型号之后,出来其次个概念:确定使用的编程环境。
在单片机学习初期,我们可能会弱化做PCB板子的概念,但是编程的概念肯定要强化。
所以在初期你手里假如有一块单片机的开发板是很有必要的。
编程环境是由所选择的单片机来确定的,比如说前边两款单片机都可以使用keil来编程,所以你要安装keil的编程环境,keil4的启动界面如下图所示:编写好的程序,如何下载到单片机去执行?所以第三个概念:下载器。
下载器的选择也是有单片机的型号来确定的,以上两款单片机都可以通过USB/TTL或者是JLINK来下载,但是这里优先推举JLINK,由于JLINK 可以实现单步调试,大大提高学习效率,便利定位、解决问题。
单片机程序架构和分层

单片机程序架构通常采用分层设计,以增强程序的可移植性、可维护性和模块化。
以下是一些常见的分层方式:
1.管理层:这一层负责整个系统的协调和管理,包括系统初始化、任务调度、资源管理等。
它通常是与硬件无关的部分,负责决策和策略的实施。
2.具体设备层:这一层包含与特定硬件设备直接交互的代码,例如按键、屏幕、传感器等。
这些代码通常包含了设备驱动程序,负责具体的硬件操作。
3.内核抽象层(KAL):这一层提供了对操作系统或内核功能的抽象,使得上层应用不需要关心底层的具体实现细节。
这样可以在不同的操作系统或内核之间移植应用程序。
4.芯片抽象层(CAL):这一层是对微控制器特定功能(如定时器、串口、ADC等)的抽象,它封装了与芯片相关的操作,为上层提供统一的接口。
5.应用层:这是最接近用户的一层,包含了用户界面、业务逻辑等。
它使用下层提供的服务来完成具体的功能。
6.驱动层:这一层包含设备的驱动程序,负责直接与硬件通信,如SPI、I2C等通信协议的实现。
7.固件层:这是最底层,通常是由官方提供的库函数,直接对寄存器进行操作,是与硬件最接近的软件层次。
总的来说,在设计单片机程序时,采用分层思想可以提高程序的可读性和可维护性,同时也便于团队协作开发。
每一层都有其特
定的职责,上层依赖于下层提供的服务,而不需要关心服务的实现细节。
这种分层屏蔽的思想不仅存在于单片机程序设计中,也是许多复杂系统设计中的常见做法,如操作系统、网络协议等都是基于分层架构设计的。
如何学好单片机?从入门到高手的进阶方法

如何学好单片机?从入门到高手的进阶方法你知道如何学好单片机吗?无论是作为一名业余的电子爱好者还是一名电子行业的相关从业人员,掌握单片机技术无疑可以使您如虎添翼,为您的电子小制作或者开发设计电子产品时打开方便的大门!学习单片机技术有一定的难度,不花费一番努力是很难学会的,但是只要不断努力就一定能成功,套用一句广告歌词:努力总有回报!第一步:基础理论知识学习基础理论知识包括模拟电路、数字电路和C语言知识。
模拟电路和数字电路属于抽象学科,要把它学好还得费点精神。
在你学习单片机之前,觉得模拟电路和数字电路基础不好的话,不要急着学习单片机,应该先回顾所学过的模拟电路和数字电路知识,为学习单片机加强基础。
否则,你的单片机学习之路不仅会很艰难和漫长,还可能半途而废。
笔者始终认为,扎实的电子技术基础是学好单片机的关键,直接影响单片机学习入门的快慢。
有些同学觉得单片机很难,越学越复杂,最后学不下去了。
有的同学看书时似乎明白了,可是动起手来却一塌糊涂,究其原因就是电子技术基础没有打好,首先被表面知识给困惑了。
单片机属于数字电路,其概念、术语、硬件结构和原理都源自数字电路,如果数字电路基础扎实,对复杂的单片机硬件结构和原理就能容易理解,就能轻松地迈开学习的第一步,自信心也会树立起来。
相反,基础不好,这个看不懂那个也弄不明白,越学问题越多,越学越没有信心。
如果你觉得单片机很难,那就应该先放下单片机教材,去重温数字电路,搞清楚触发器、寄存器、门电路、COMS电路、时序逻辑和时序图、进制转换等理论知识。
理解了这些知识之后再去看看单片机的结构和原理,我想你会大彻大悟,信心倍增。
模拟电路是电子技术最基础的学科,她让你知道什么是电阻、电容、电感、二极管、三极管、场效应管、放大器等等以及它们的工作原理和在电路中的作用,这是学习电子技术必须掌握的基础知识。
一般是先学习模拟电路再去学习数字电路。
扎实的模拟电路基础不仅让你容易看懂别人设计的电路,而且让你的设计的电路更可靠,提高产品质量。
单片机基础知识点全攻略

单片机基础知识点全攻略单片机 (Microcontroller) 是一种内含的微处理器、存储器以及各种输入输出接口的集成电路芯片。
它广泛应用于各种嵌入式系统中,如家电、汽车、电子设备等。
单片机的基础知识点主要包括以下几个方面:1.单片机的基本结构:单片机由中央处理器单元(CPU)、存储器、输入输出(I/O)接口和定时器/计数器等组成。
其中,CPU是单片机最重要的部件,负责执行程序指令。
存储器可分为随机存取存储器(RAM)和只读存储器(ROM),其中ROM存储着程序代码和常量数据,RAM用于存储运行时的数据。
2.单片机的工作原理:单片机通过执行存储在ROM中的程序指令,完成各种任务。
CPU从ROM中读取指令并执行,将结果存储在RAM中。
由于单片机通常工作在时钟信号的控制下,故CPU在时钟的辅佐下工作。
3.单片机的编程语言:单片机的编程语言通常采用汇编语言或高级语言(如C语言)。
汇编语言是一种机器指令的助记符,编程复杂、灵活、直接,通常用于对程序执行效率要求较高的场合;而C语言则具有语法简洁、易读易写的特点,适合快速开发程序。
4.单片机的输入输出接口:单片机通过输入输出接口与外部设备进行数据交互。
常见的输入接口有开关、按钮、传感器等;常见的输出接口有LED灯、蜂鸣器、电机等。
通过编程,用户可以控制这些接口的状态,与外设实现数据的输入和输出。
5.单片机的定时器/计数器:单片机的定时器/计数器模块用于生成精确的时间间隔或计数外部事件。
它可以被用来实现定时中断、测量脉冲宽度、计数等功能,是单片机中非常重要的功能模块之一6.单片机的中断和中断服务程序:单片机在执行程序的过程中,可以接收和响应外部的中断信号。
当中断发生时,单片机会立即暂停当前任务,跳转执行预先定义好的中断服务程序,处理中断事件。
中断机制是实现实时响应和多任务操作的重要手段。
7.单片机的电源与时钟:单片机需要稳定可靠的电源和时钟信号供给。
电源通常由直流电源或电池提供,特别是在嵌入式系统中,通常需要考虑功耗和电池寿命等因素;时钟信号则是单片机正常工作的基础,它通过晶体振荡电路或者外部时钟源提供。
单片机程序架构详解篇

单片机程序架构详解一、前言单片机,也称为微控制器(Microcontroller),是将计算机的体系结构集成到一个芯片上的微型计算机。
由于其体积小、成本低、可靠性高等特点,单片机在工业控制、智能仪表、家用电器等领域得到了广泛应用。
了解单片机的程序架构是编写和优化单片机程序的关键。
二、单片机程序架构概述单片机的程序架构主要由以下几个部分组成:1. 硬件抽象层(HAL):这一层为上层软件提供了一个与硬件无关的接口,使得软件可以独立于硬件进行开发和运行。
HAL层通常包括对单片机各种外设(如GPIO、UART、SPI、PWM等)的操作函数。
2. 系统服务层:这一层提供了系统级的各种服务,如任务调度、内存管理、时间管理等。
这些服务使得上层应用程序可以更加专注于业务逻辑的实现。
3. 应用层:这是最上层,直接面向用户,包含了各种应用程序的逻辑代码。
三、各层详解1. 硬件抽象层(HAL)硬件抽象层(HAL)是单片机程序架构中非常重要的一层,其主要目标是使得硬件相关的操作与具体的硬件实现无关。
这样,当硬件平台发生变化时,只要HAL层设计得当,上层代码就不需要改变。
HAL层通常包括以下内容:* 各种外设寄存器的操作函数:例如,GPIO的输入输出函数、UART的发送接收函数等。
这些函数隐藏了具体的寄存器操作细节,使得开发者只需要关注功能实现而不需要关心底层寄存器的操作。
* 硬件初始化函数:用于在系统启动时对单片机进行初始化,如配置时钟、启动看门狗等。
* 中断处理函数:用于处理单片机的各种中断事件,如定时器溢出、串口接收等。
2. 系统服务层系统服务层提供了单片机操作系统所需的各种服务,如任务调度、内存管理、时间管理等。
这些服务使得上层应用程序可以更加专注于业务逻辑的实现。
以下是一些常见的系统服务:* 任务调度:多任务环境下,任务调度器负责分配CPU时间给各个任务,使得各个任务能够按需运行。
* 内存管理:负责动态内存的分配和释放,如堆和栈的管理。
单片机教学大纲(两篇)2024

引言概述:正文内容:1.硬件设备与基本概念1.1单片机基础知识1.1.1单片机的定义和分类1.1.2单片机的结构和工作原理1.1.3单片机的常用引脚功能与连接方法1.2单片机开发板选型与使用1.2.1不同型号单片机开发板的特点和功能1.2.2单片机资源配置与接口扩展1.2.3单片机开发环境的搭建和使用方法2.嵌入式C语言编程基础2.1C语言基本语法2.1.1数据类型与变量2.1.2运算符和表达式2.1.3控制结构与循环语句2.2单片机C语言编程入门2.2.1I/O口配置与控制2.2.2延时和定时器控制2.2.3中断处理3.单片机外设驱动3.1数码管与LED显示驱动3.1.1数码管的原理与显示方法3.1.2数码管驱动电路设计与编程实现3.2液晶显示屏驱动3.2.1液晶显示驱动的原理3.2.2液晶显示屏驱动电路设计与编程实现3.3三轴加速度传感器驱动3.3.1三轴加速度传感器基本原理3.3.2传感器接口与数据读取4.串口通信与通信协议4.1串口通信基础4.1.1串口通信协议与通信波特率4.1.2串口通信硬件连接与配置4.2单片机与PC的串口通信4.2.1串口通信的原理与方法4.2.2串口通信协议的设计与实现4.3单片机与其他设备的串口通信4.3.1串口通信的硬件连接与配置4.3.2串口通信协议的设计与实现5.单片机应用开发5.1温湿度监测系统5.1.1温湿度传感器的原理和接口设计5.1.2数据采集与显示控制的编程实现5.2无线通信系统5.2.1无线通信模块与单片机的接口设计5.2.2数据传输与接收的编程实现5.3蜂鸣器音乐播放系统5.3.1蜂鸣器的基本工作原理和控制方法5.3.2音乐资源的存储与播放控制的编程实现总结:本教学大纲以逻辑顺序将单片机教学内容进行了详细介绍,从硬件设备与基本概念开始,逐步向学生展示了单片机开发的全过程。
通过掌握单片机编程的基本原理和实践技巧,学生将能够应用单片机实现各种嵌入式应用。
手把手教你学51单片机(C语言版)

12.3.1 常量和符 号常量
A
12.3.2 字符和字 符串数组实例
B
12 指针基础与1602液晶的初步认识
1
12.4.1 1602液晶的硬件接口 介绍
2
12.4.2 1602液晶的读写时序 介绍
3
12.4.3 1602液晶的指令介绍
4
12.4.4 1602液晶简单实例
01
8.1.1 电 源
02
8.1.2 晶 振
03
8.1.3 复 位电路
8.1 单片机最小系统
0 1
8.4.1 独立按
键
0 2
8.4.2 矩阵按
键
0 3
8.4.3 独立按
键的扫描
0 4
8.4.4 按键消
抖
0 5
8.4.5 矩阵按
键的扫描
8 函数进阶与按键
8.4 按键
10
Part One
9 步进电机与蜂鸣器
11.3 USB转串口 通信
11.4 IO口模拟 UART串口通信
11.5 UART串口 通信的基本应用
11.6 通信实例与 ASCII码
11 UART串口通 信
11.7 练习题
11.5.1 通信的三种基本类 型
11.5.3 UART串口程序
11 UART串口通信
11.5 UART串口通信的基本应用
10.1.3 字节操作修改位的 技巧
10.1.5 秒表程序
10 实例练习与经验积累
10.1 数字秒表实例
10.1.2 定时时间精准性调 整
10.1.4 数码管扫描函数算 法改进
12
Part One
初学者如何学习单片机

初学者如何学习单片机单片机学习步骤第一步:数字I/O的使用使用按钮输入信号,发光二极管显示输出电平,就可以学习引脚的数字I/O功能,在按下某个按钮后,某发光二极管发亮,这就是数字电路中组合逻辑的功能,虽然很简单,但是可以学习一般的单片机编程思想,例如,必须设置很多寄存器对引脚进行初始化处理,才能使引脚具备有数字输入和输出输出功能。
每使用单片机的一个功能,就要对控制该功能的寄存器进行设置,这就是单片机编程的特点,千万不要怕麻烦,所有的单片机都是这样第二步:定时器的使用学会定时器的使用,就可以用单片机实现时序电路,时序电路的功能是强大的,在工业、家用电气设备的控制中有很多应用,例如,可以用单片机实现一个具有一个按钮的楼道灯开关,该开关在按钮按下一次后,灯亮3分钟后自动灭,当按钮连续按下两次后,灯常亮不灭,当按钮按下时间超过2s,则灯灭。
数字集成电路可以实现时序电路,可编程逻辑器件PLD可以实现时序电路,可编程控制器PLC也可以实现时序电路,但是只有单片机实现起来最简单,成本最低。
定时器的使用是非常重要的,逻辑加时间控制是单片机使用的基础。
第三步:中断单片机的特点是一段程序反复执行,程序中的每个指令的执行都需要一定的执行时间,如果程序没有执行到某指令,则该指令的动作就不会发生,这样就会耽误很多快速发生的事情,例如,按钮按下时的下降沿。
要使单片机在程序正常运行过程中,对快速动作做出反应,就必须使用单片机的中断功能,该功能就是在快速动作发生后,单片机中断正常运行的程序,处理快速发生的动作,处理完成后,在返回执行正常的程序。
中断功能使用中的困难是需要精确地知道什么时候不允许中断发生屏蔽中断、什么时候允许中断发生开中断,需要设置哪些寄存器才能使某种中断起作用,中断开始时,程序应该干什么,中断完成后,程序应该干什么等等。
中断学会后,就可以编制更复杂结构的程序,这样的程序可以干着一件事,监视着一件事,一旦监视的事情发生,就中断正在干的事情,处理监视的事情,当然也可以监视多个事情,形象的比喻,中断功能使单片机具有吃着碗里的,看着锅里的功能。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
手把手教你学单片机进阶教程
框架篇(上)
本篇里我们聊一聊软件框架,那么什么是框架呢?它又有什么用处呢?
软件框架,说简单一点就是我们组织软件的方式,没有框架的代码,模块是乱添的,写程序的人也不知道要添在哪里,只知道加在这里可以用,放在这里就行。
有框架的代码,模块应该添加到哪里是清楚的。
曾经看过一句话说的挺有道理,“一个好的程序架构,是一个有经验的工程师和一个初学者的分水岭”,我们在单片机软件中用的最多的结构莫过于下面这样的:
1While(1)
2{
3Led_on();
4i = 1000;
5While(i--);
6Led_off();
7}
当我们刚开始学习的时个,程序比较简单,这样单纯的结构还是可以应付的。
但是如果当我们真的要做一个系统级的工程的时候,有很多功能要处理,这样的结构显然就不能适应了,只那一个“while(i--)”就不知道耽误了多少事儿。
到这里有人要说了,工程复杂的时候我可以跑个OS。
可以说RTOS对于功能复杂的嵌入式系统来说是个非常好的解决方案,如比较出名的RT-Thread (我们以后会推出这个的专题),uc/os-ii。
不过,可惜的是,操作系统对于51来说有点太,系统的开销有可能比应用占用的资源的还要多。
那么我们就自己动手来打造一个小资源单片机适用的框架吧。
我们将实现两个版本,其内在思想都是一样的,一个简单点,占用资源更小。
一个稍复杂些,
pzq@/csh@sparkcn
但更灵活。
大家可以根据情况选用。
easy_framework
我们把这个框架暂时命名为easy_framework,这里我们仅提供思想和基本的代码。
完整的代码可以在我们提供代码包(下载地址见文章最后)里找到。
这里测试和实验的硬件环境是Spark51学习板。
大家如果有需要,可以到我们工作室店铺购买或直接通过QQ联系我们首先使用一个Timer来产生一个1m的定时中断。
在51单片机上,这里选用Timer0
1init_sys_timer()
2{
3/*T0 1方式*/
4TMOD |= 0x01;
5/*设定1m的计时*/
6TL0 = (u8)SYS_TIMER_INIT_VALUE;
7TH0= (u8)(SYS_TIMER_INIT_VALUE >> 8);
8/*允许中断*/
9ET0 = 1;
10TR0 = 1;
11}
通过上面这个函数产生一个1m的中断,在其“中断服务函数”里我们对一些时间标志量进行记数
1/*Timer 0中断服务程序*/
2void proc_sys_tick() interrupt 1
3{
4TR0 = 0;
5Cnt5ms++;
pzq@/csh@sparkcn
6Cnt10ms++;
7Cnt20ms++;
8Cnt50ms++;
9Cnt100ms++;
10/*处理1ms 任务*/
11task_1ms_period();
12/*如果需要非常精确的1ms,这里需要做初值的修正*/
13TL0 = (u8)SYS_TIMER_INIT_VALUE;
14TH0= (u8)(SYS_TIMER_INIT_VALUE >> 8);
15TR0 = 1;
16}
每中断一次,这些时间示志量会加1,在主程序里我们会用到这些标志。
主程序如下:
1void main(void)
2{
3/* 要用到1秒的任务,放到100ms里计时*/
4u8 cnt_1000ms = 0;
5/*硬件相关初始化*/
6init_somthing();
7init_sysclk();
8EA = 1;
9while (1)
10{
11/*5 ms 定时到,执行10ms周期任务*/
12if (Cnt5ms >= 5)
13{
14Cnt5ms = 0;
15task_5ms_period();
16}
pzq@/csh@sparkcn
17/*10 ms 定时到,执行10ms周期任务*/
18if (Cnt10ms >= 10)
19{
20Cnt10ms = 0;
21task_10ms_period();
22}
23/*100ms 定时到,执行10ms周期任务*/
24if (Cnt100ms >= 100)
25{
26Cnt100ms = 0;
27task_100ms_period();
28cnt_1000ms++;
29
30/*在100ms的任务里为1000ms的任务计时*/
31if (cnt_1000ms >= 10)
32{
33cnt_1000ms = 0;
34/* 1000ms */
35task_1000ms_period();
36}
37}
38}
39}
到这里,easy_framework已经完全浮出水面了。
我们把系统划分成若干个周期性运行的任务,只需要完成相应的任务函数即可,这种“划分任务,分时运行”的方式也是RTOS的基本思想。
通过这种划分,我们对整个系统的运行情况了解的非常清楚,再也不用发愁新加的模块放到哪里合适了。
而easy_framework的使用的资源仅仅是一个定时器和几个变量而已。
pzq@/csh@sparkcn
pzq@/csh@sparkcn
实验
下面就用这个框架写个简单的流水灯的的例子看一下(完整的例子在代码包里可以找到),我们的实验平台如下:
实验平台: Spark51开发板
编程环境:TKStudio + KEIL 9.0
Spark51学习板上有
8个LED 灯,其连接的原理图如下,也可以参考学习板的整体原理图(学习板的资料里有)
这8个LED 是按共阳级连接的,公共端通过74HC138的一个输出来控制,使公共输出控制端即LEDS6输出低,三极管导通,相应选择端输出低即可点亮对应的LED 灯了。
下面是流水灯的代码
1void led_test()
2{
3static u8 p1_value = 0x01;
4ADDR2 = 1;
5ADDR1 = 1;
6ADDR0 = 0;
7ADDR3 = 1;
8ENLED = 0;
9
10P0 = ~p1_value;
11p1_value <<= 1;
12if (0 == p1_value)
13{
14p1_value = 0x01;
15}
16}
任务代码:
1void task_100ms_period()
2{
3led_test();
4}
是不是见不到讨厌的while(i--)了,把程序编译好下到Spark51学习板里看一下效果。
如果想调整流水灯的频率,把这段代码放到另一个task_XXms_period()里就可以了,是不是很方便。
思考
一个方便、精简的框架搭建好了,我们写程序就方便了。
但我们高兴的同时还需要思考一下几个问题:
pzq@/csh@sparkcn
1这样框架有什么局限性?
a)思路一:怎么实现一个可变流水速度的流水灯
b)思路二:各任务运行的时机效率是否达到最高
2代码中有一句注释“/*如果需要非常精确的1ms,这里需要做初值的修正*/”,应该怎样修正?
欢迎就以上问题与我们交流、讨论,我们的联系方式QQ:pzq@ 或csh@
下篇预告
在下一篇文章我们将和大家一起构建另一个软件框架mini_framework。
比easy_framework灵活、方便。
Are U Ready ?Let’s Go!
作者简介
Spark嵌入式工作室,成立于2010年,致力于嵌入式方面的软、硬件开发和研究,团队成员都是有经验的开发工程师,擅长使用51单片机、STM32。
联系方式QQ:pzq@
csh@
验证码:spark
QQ技术交流群:186232047
代码包下载地址:或直接到群里共享下载
pzq@/csh@sparkcn
参考资料
pzq@/csh@sparkcn。