初学者即将毕业实习,希望利用最后两个月的学习顺利找到工作,占个地方做些笔记O(∩_∩)O哈哈~

2019-07-20 23:27发布

本帖最后由 229382777@qq.com 于 2017-2-28 10:58 编辑

        买了原子的mini开发板快一年了,一直都是断断续续的学,学习进度经常被打断,导致现在连前面的知识也忘的差不多了,自身学习的条件可能没有大学生好,即将面临毕业实习,希望在最后这两个月能把mini教程全部过完并掌握,争取出去后能适应的了这方面的工作。在此借原子哥的宝地一用,也方便自己日后的复习,学习过程中可能会出现挺多错误的地方,也希望大家能帮忙指出其中错误的地方。为了保证自己的身体健康,不忙的情况下一般都会晚上9点前进行更新,每天会坚持去操场跑步。希望各位也注重身体健康,身体是革命的本钱O(∩_∩)O!

目录

所在页数 所在楼层楼层主题 1
1
1
1
1
1
1
1
2
2
2
2
2
2
2
2
3
3
3
3
3
3
3
3
4
4
4
4
4
4
4
4
4
4
4
42#  
20#
25#
32#
38#
41#
44#
46#
54#
59#
60#
63#
71#
78#
85#
86#
100#
106#
110#
117#
122#
134#
144#
148#
152#
154#
155#
158#
163#
164#
167#
171#
173#
176#
185#
189#之后硬件篇
SYSTEM文件部分(一)
SYSTEM文件部分(二)
LED灯
按键
串口
外部中断
独立、窗口看门狗
定时器中断
PWM互补输出及死区时间
输入捕获
OLED
LCD
LCD(二)
RTC
待机唤醒
ADC
内部温度传感器
DAC
DMA
IIC
SPI
触摸屏
FLASH模拟EEPROM
内存管理
SD卡
FATFS
汉字显示实验
图片显示
IAP
触控USB鼠标实验
M3内核基础知识
UCOS任务调度
UCOS信号量和邮箱
消息队列、信号量、软件定时器
知识点分享
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
55条回答
it_do_just
1楼-- · 2019-07-21 00:21

按照原子哥的mini教程顺序的学一遍,先是简单的硬件部分

硬件篇
:(以下部分由自己通过网络查找资料和自己总结的一些内容)

硬件篇的内容寄存器版本和库函数的版本没有什么差别



USB电源+5V通过AMS1117-3.3的稳压芯片降压到3.3V供给MCU,回路中有500mA的自恢复保险丝进行保护

通过 F1(自恢复保险丝)接到右侧,在正常工作的情况下,保险丝可以直接看成导线,自恢复保险丝的作用是,当你后级电路哪个地方有发生短路的时候,保险丝会自动切断电路,保护开发板以及电脑的 USB 口,当电路正常后,保险丝会恢复畅通,正常工作。

AMS1117-3.3V:AMS1117的片上微调把基准电压调整到1.5%的误差以内,而且电流限制也得到了调整,以尽量减少因稳压器和电源电路超载而造成的压力。


电容:可以看到稳压芯片的两边各有一个0.1uF220uF的电容

首先了解电容前先说一下电容的必要性

电磁干扰EMI:去耦电容的应用。首先要介绍一下去耦电容的应用背景,这个背景就是电磁干扰,也就是“传说中”的EMI。举几个例子:冬天比较干燥的时候手触碰到电脑外壳、铁柜子等物品的时候会被点击,这就是“静电放电”现象,也称为ESD。老式的收音机和电视会出现杂音,这就是“快速瞬间群脉冲”的效果,也称之为 EFT。以前的老电脑,有的性能不是很好,带电热插拔优盘、移动硬盘等外围设备的时候,内部会产生一个百万分之一秒的电源切换,直接导致电脑出现蓝屏或者重启现象,就是热插拔的“浪涌”效果,称之为 Surge。电磁干扰的内容有很多,有些内容非常重要。这些问题大家不要认为是小问题,比如一个简单的静电放电,我们用手能感觉到的静电,可能已经达到 3KV 以上了,如果用眼睛能看得到的,至少是 5KV 了,只是因为这个电压虽然很高,能量却非常小,持续的时间非常短,因此不会对人体造成伤害。但是应用的这些半导体元器件就不一样了,一旦瞬间电压过高,就有可能造成器件的损坏。而且,即使不损坏也已经严重干扰到设备的正常使用了。基于以上的这些问题,就诞生了电磁兼容(EMC)这个名词。

 

去耦电容:

回到那幅图的两个电容上面,容值比较大的电容220uF那个,理论上可以理解成水缸或者水池子,同时,可以直接把电流理解成水流。

作用一:缓冲作用。当上电的瞬间,电流从电源处流下来的时候,不稳定,容易冲击电子器件,加个电容可以起到缓冲作用。就如同我们直接用水龙头的水浇地,容易冲坏花花草草。我们只需要在水龙头处加个水池,让水经过水池后再缓慢流进草地,就不会冲坏花草,起到有效的保护作用。

作用二:稳定作用。后级电子器件的功率大小都不一样,而器件正常工作的时候,所需电流的大小也不是一成不变的。比如后级有个器件还没有工作的时候,电流消耗是 100mA,突然它参与工作了,电流猛的增大到了 150mA,这个时候如果没有一个水缸的话,电路中的电压(水位)就会直接突然下降。而电路中有些电子元器件,必须高于一定的电压才能正常工作,电压太低就直接不工作了,这个时候水缸就必不可少了。电容会在这个时候把存储在里边的电量释放一下,稳定电压。电容的选取,第一个参数是耐压值的考虑。USB的5V 系统,电容的耐压值要高于5V,一般推荐 1.5 倍到 2 倍即可。第二个参数是电容容值,这个就需要根据经验来选取了,选取的时候,要看这个电容起作用的整套系统的功率消耗情况,如果系统耗电较大,波动可能比较大,那么容值就要选大一些,反之可以小一些。比如上边讲电容作用二的时候,电流从 100mA 突然增大到 150mA 的时候,其实即使加上这个电容,电压也会轻微波动,比如从 3.3V 波动到 3.2V,但是只要板子上的器件在电压 3.2V 以上也可以正常工作的话,这点波动是被容许的,但是如果不加或者加的很小,电压波动比较大,有些器件的工作就会不正常了。但是如果加的太大,占空间并且价格也高,所以这个地方电容的选取多参考经验。

 

再看一下那个比较小的电容(104):它容值较小,是 0.1uF,也就是 100nF,是用来滤除高频信号干扰的。比如 ESD, EFT 等。初中学过电容的特性——可以通交流隔直流,但是电容的参数对不同频率段的干扰的作用是不一样的。这个 100nF 的电容,是前辈根据干扰的频率段,根据板子的参数,根据电容本身的参数所总结出来的一个值。也就是说,以后在设计数字电路的时候,在电源处的去耦高频电容,直接用这个 0.1uF 就可以了。还有在所有的 IC 器件的 VCC 和 GND 之间,都会放一个 0.1uF 的高频去耦电容,特别在布板的时候,这个 0.1uF 电容要尽可能的靠近 IC,尽量很顺利的与这个 IC 的 VCC 和 GND 连到一起。

 

SMBJ5.0A和SMBJ3.3A:SMBJ表示TVS管的系列

TVS或称瞬变电压抑制二极管是在稳压管工艺基础上发展起来的一种新产品,其电路符号和普通稳压二极管相同,外形也与普通二极管无异,当TVS管两端经受瞬间的高能量冲击时,它能以极高的速度(最高达1*10-12秒)使其阻抗骤然降低,同时吸收一个大电流,将其两端间的电压箝位在一个预定的数值上,从而确保后面的电路元件免受瞬态高能量的冲击而损坏。属于防过电压、过电流的保护元件。


晶振:

晶振通常分为无源晶振和有源晶振两种类型,无源晶振一般称之为 crystal(晶体),而有源晶振则叫做 oscillator(振荡器)。有源晶振是一个完整的谐振振荡器,它是利用石英晶体的压电效应来起振,所以有源晶
振需要供电,当我们把有源晶振电路做好后,不需要外接其它器件,只要给它供电,它就可以主动产生振荡频率,并且可以提供高精度的频率基准,信号质量也比无源信号要好。无源晶振自身无法振荡起来,它需要芯片内部的振荡电路一起工作才能振荡,它允许不同的电压,但是信号质量和精度较有源晶振差一些。相对价格来说,无源晶振要比有源晶振价格便宜很多。无源晶振两侧通常都会有个电容,一般其容值都选在 10pF~40pF 之间,如果手册中有具体电容大小的要求则要根据要求来选电容,原子哥使用的是 22pF 就是比较好的选择,这是一个长久以来的经验值,具有极其普遍的适用性。

 

上下拉电阻:

上拉电阻就是将不确定的信号通过一个电阻拉到高电平,同时此电阻也起到一个限流作用,下拉就是下拉到低电平。比如我们的 IO 设置为开漏输出高电平或者是高阻态时,默认的电平就是不确定的,外部经一个电阻接到 VCC,也就是上拉电阻,那么相应的引脚就是高电平;经一个电阻到 GND,也就是下拉电阻,那么相应的引脚就是一个低电平。上拉电阻应用很多,都可以起到什么作用呢?现在主要先了解最常用的以下 4 点。
1、 OC 门要输出高电平,必须外部加上拉电阻才能正常使用,其实 OC 门就相当于单片机 IO 的开漏输出。

2、加大普通 IO 口的驱动能力。单片机内部 IO 口的上拉电阻,一般都是在几十K 欧,因此外部加个上拉电阻,可以形成和内部上拉电阻的并联结构,增大高电平时电流的输出能力。

3、在电平转换电路中,比如和三极管配合使用,可以利用三极管开关作用3.3V去控制12V电压,这里的上拉电阻其实起到的是限流电阻的作用.

4、单片机中未使用的引脚,比如总线引脚,引脚悬空时,容易受到电磁干扰而处于紊乱状态,虽然不会对程序造成什么影响,但通常会增加单片机的功耗,加上一个对 VCC 的上拉电阻或者一个对 GND 的下拉电阻后,可以有效的抵抗电磁干扰。那么在进行电路设计的时候,又该如何选择合适的上下拉电阻的阻值呢?
1、从降低功耗的方面考虑应当足够大,因为电阻越大,电流越小。
2、从确保足够的引脚驱动能力考虑应当足够小,电阻小了,电流才能大。

3、在开漏输出时,过大的上拉电阻会导致信号上升沿变缓。我们来解释一下:实际电平的变化都是需要时间的,虽然很小,但永远都达不到零,而开漏输出时上拉电阻的大小就直接影响了这个上升过程所需要的时间。想一下,如果电阻很大,而信号频率又很快的话,最终将导致信号还没等上升到高电平就又变为低了,于是信号就无法正确传送了。

综合考虑各种情况,我们常用的上下拉电阻值大多选取在 1K 到 10K 之间,具体到底多大通常要根据实际需求来选,通常情况下在标准范围内就可以了,不一定是一个固定的值。

 

三极管(Q1为NPN,Q2为PNP):只考虑上面原理图的三极管用法(开关特性)

三极管的用法特点,关键点在于 b 极(基极)和 e 级(发射极)之间的电压情况,对于PNP 而言, e 极电压只要高于 b 级 0.7V(硅管) 以上,这个三极管 e 级和 c 级之间就可以顺利导通。也就是说,控制端在 b 和 e 之间,被控制端是 e 和 c 之间。同理, NPN 型三极管的导通电压是 b 极比 e 极高 0.7V(硅管),总之是箭头的始端比末端高 0.7V(硅管) 就可以导通三极管的 e 极和 c 极。
it_do_just
2楼-- · 2019-07-21 01:04
本帖最后由 229382777@qq.com 于 2016-1-6 16:05 编辑

感觉坛友这两篇关于汇编的文档写的不错,分享给大家,建议看一下
原网址在:http://www.openedv.com/forum.php?mod=viewthread&tid=45361
龙之谷
3楼-- · 2019-07-21 04:31
顶一下,支持++
it_do_just
4楼-- · 2019-07-21 10:08
最新更新部份,由于时间原因要出去游玩两天,所以更新比较急,发现有些地方没备注好,附件都得等回来补
it_do_just
5楼-- · 2019-07-21 15:28

实战:串口

 

USART介绍

通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。 USART利用分数波特率发生器提供宽范围的波特率选择。它支持同步单向通信和半双工单线通信,也支持LIN(局部互连网),智能卡协议和IrDA(红外数据组织)SIR ENDEC规范,以及调制解调器(CTS/RTS)操作。它还允许多处理器通信。使用多缓冲器配置的DMA方式,可以实现高速数据通信。

 

任何USART双向通信至少需要两个脚:接收数据输入(RX)和发送数据输出(TX)。

RX:接收数据串行输入。通过采样技术来区别数据和噪音,从而恢复数据。
TX:发送数据输出。当发送器被禁止时,输出引脚恢复到它的I/O端口配置。当发送器被激活,并且不发送数据时,TX引脚处于高电平。在单线和智能卡模式里,此I/O口被同时用于数据的发送和接收。

 

偶校验:校验位使得一帧中的7或8个LSB数据以及校验位中’1’的个数为偶数。
例如:数据=00110101,有4个’1’,如果选择偶校验(在USART_CR1中的PS=0),校验位将是’0’。
奇校验:此校验位使得一帧中的7或8个LSB数据以及校验位中’1’的个数为奇数。
例如:数据=00110101,有4个’1’,如果选择奇校验(在USART_CR1中的PS=1),校验位将是’1’。
传输模式:如果USART_CR1的PCE位被置位,写进数据寄存器的数据的MSB位被校验位替换后发送出去(如果选择偶校验偶数个’1’,如果选择奇校验奇数个’1’)。如果奇偶校验失败,USART_SR寄存器中的PE标志被置’1’,并且如果USART_CR1寄存器的PEIE在被预先设置的话,中断产生。

 

串口各种模式的设置

同步模式:通过在USART_CR2寄存器上写CLKEN位选择同步模式。

LIN(局域互联网)模式:是通过设置USART_CR2寄存器的LINEN位选择。

单线半双工模式:通过设置USART_CR3寄存器的HDSEL位选择。

智能卡模式:设置USART_CR3寄存器的SCEN位选择智能卡模式。

IrDA模式:通过设置USART_CR3寄存器的IREN位选择IrDA模式。

串口DMA发送接收:USART可以利用DMA连续通信。 Rx缓冲器和Tx缓冲器的DMA请求是分别产生的。使用DMA进行发送,可以通过设置USART_CR3寄存器上的DMAT位激活。可以通过设置USART_CR3寄存器的DMAR位激活使用DMA进行接收

 

串口设置

1,串口时钟使能:APB1ENR或APB2ENR

2,串口复位:APB1RSTR或APB2RSTR

3,串口波特率设置:USART_BRR(通过计算,上面笔记有)

4,串口控制:USART_CR1~3,中文参考手册542~546页,内容比较多

5,数据发送与接收:USART_DR

6,串口状态:USART_SR

 

USART_SR 状态寄存器

比较重要的两个位

RXNE(读数据寄存器非空),当该位被置 1 的时候,就是提示已经有数据被接收到了,并
且可以读出来了。这时候我们要做的就是尽快去读取 USART_DR,通过读 USART_DR 可以将
该位清零,也可以向该位写 0,直接清除。
TC(发送完成),当该位被置位的时候,表示 USART_DR 内的数据已经被发送完成了。如
果设置了这个位的中断,则会产生中断。该位也有两种清零方式: 1)读 USART_SR,写
USART_DR。 2)直接向该位写 0。

 

USART_DR寄存器

DR[8: 0]为串口数据,包含了发送或接收的数据。由于它是由两个寄存器组成的,一个给
发送用(TDR),一个给接收用(RDR),该寄存器兼具读和写的功能。 TDR 寄存器提供了内部总
线和输出移位寄存器之间的并行接口。 RDR 寄存器提供了输入移位寄存器和内部总线之间的并
行接口。如下图



半主机模式:
半主机是用于 ARM 目标的一种机制,可将来自应用程序代码的输入/输出请求传送至运行调试器的主机。例如,使用此机制可以启用 C 库中的函数,如 printf() 和 scanf(),来使用主机的屏幕和键盘,而不是在目标系统上配备屏幕和键盘。

这种机制很有用,因为开发时使用的硬件通常没有最终系统的所有输入和输出设备。 半主机可让主机来提供这些设备。半主机是通过一组定义好的软件指令(如 SVC)来实现的,这些指令通过程序控制生成异常。 应用程序调用相应的半主机调用,然后调试代理处理该异常。 调试代理提供与主机之间的必需通信。
简单的来说,半主机模式就是通过仿真器实现开发板在电脑上的输入和输出。机制的运行需要仿真器,否则无法运行, 开发式一般单片机需要独立运行,开发者应去掉仿真器,把printf函数通过单片机的外设来实现,例如通过开发板的串口,lcd或者sd卡。

以下是串口初始化代码
[mw_shl_code=c,true]void uart_init(u32 pclk2,u32 bound) { float temp; u16 mantissa; u16 fraction; temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV,前面的笔记已经解释,这里就不重复了 mantissa=temp; //得到整数部分 fraction=(temp-mantissa)*16; //得到小数部分 mantissa<<=4; mantissa+=fraction; RCC->APB2ENR|=1<<2; //使能PORTA口时钟 RCC->APB2ENR|=1<<14; //使能串口时钟 GPIOA->CRH&=0XFFFFF00F;//IO状态设置 GPIOA->CRH|=0X000008B0;//IO状态设置 RCC->APB2RSTR|=1<<14; //复位串口1 RCC->APB2RSTR&=~(1<<14);//停止复位 //波特率设置 USART1->BRR=mantissa; // 波特率设置 USART1->CR1|=0X200C; //1位停止,无校验位(原子哥这里应该备注错误了,停止位是通过CR2的12和13位来设置的,CR1设置不了,这里应该备注为USART使能,发送接收使能) #if EN_USART1_RX //如果使能了接收 //使能接收中断 USART1->CR1|=1<<8; //PE中断使能 USART1->CR1|=1<<5; //接收缓冲区非空中断使能 MY_NVIC_Init(3,3,USART1_IRQn,2);//组2,最低优先级 #endif } [/mw_shl_code]

上面初始化过程也发现原子哥有个备注写错了,USART1->CR1|=0X200C;备注的是1位停止位,停止位是通过CR2的12和13位来设置的,CR1设置不了,这里应该备注为USART使能,发送接收使能。

 

关于原子哥的中断处理函数也写的非常好,自己也用之前学过的位字段的方式改了一下代码,原理都差不多,原子哥用16位的变量当做寄存器操作,0~13位用于保存字节数,14和15位用于判断换行符来标示结束,用位字段主要考虑到程序的可读性,因为原子哥的标志位没有明确指令其作用,而用位字段能清晰的描述,当然,考虑到程序的效率,当然还是原子哥的方法好。以下附上我修改过的代码
[mw_shl_code=c,true]typedef struct{ unsigned REC_Num : 14; //前0~13位保存接收到的字节数 unsigned REC_0X0D : 1; //收到0x0d表示换行 unsigned REC_END : 1; //结束一次接收 }usart_rx_sta; usart_rx_sta USART_RX_STA; //接收状态标记 void USART1_IRQHandler(void) { u8 res; if(USART1->SR&(1<<5))//接收到数据 { res=USART1->DR; if(USART_RX_STA.REC_END == 0)//接收未完成 { if(USART_RX_STA.REC_0X0D == 1)//接收到了0x0d { if(res!=0x0a) memset(&USART_RX_STA, 0 ,sizeof(USART_RX_STA));//接收错误,重新开始 else USART_RX_STA.REC_END = 1; //接收完成了 }else //还没收到0X0D { if(res==0x0d)USART_RX_STA.REC_0X0D = 1; else { USART_RX_BUF[USART_RX_STA.REC_Num]=res; USART_RX_STA.REC_Num++; if(USART_RX_STA.REC_Num>(USART_REC_LEN-1)) memset(&USART_RX_STA, 0 ,sizeof(USART_RX_STA));//接收数据错误,重新开始接收 } } } } } [/mw_shl_code]

程序的运行结果都是一样的,基于考虑实际项目,串口需要有个超时机制,以下附上自己常用的超时机制的代码,如果超过50ms都还没接收到数据则强制接收结束。以下是代码

[mw_shl_code=c,true]/* * 函数名:UartRxMonitor * 描 述:UART通信接收的监控函数,用于判定一帧数据的接收完成 * 输 入:ms - 本函数调用的间隔时间,单位ms,直接开个定时器,每毫秒中断一次,形参设为1即可 * 输 出:无 */ void UartRxMonitor(u8 ms) { u8 cnt; static u8 cntbkp=0; static u8 idletmr=0; static u8 sigpost=0; cnt = usart3_get_long; //帧的长度 if (cnt == 0) { //没接收到数据 cntbkp = 0; //当前长度清零 return; } if (cnt != cntbkp) { //接收到了新数据,累加的时间清零,如果前后长度相等则开始ms的累加 idletmr = 0; //时间累计清零 sigpost = 0; //超时标志清零 cntbkp = cnt; //记下当前长度 return; } if (sigpost != 0) { //保证接收完成标志只推送一次 return; } idletmr += ms; //毫秒数累计,50ms     if (idletmr >= FRAME_SPACE_TIME) { //如果超过50ms长度依旧相等,则说明超时了,FRAME_SPACE_TIME是个宏定义,等于50 sigpost = 1; //超时标志 //可以强制接收完成 //也可以丢弃接收缓冲区的数据,看自己需求 } }[/mw_shl_code]



chinafox
6楼-- · 2019-07-21 20:28
好认真呀!中国还有你这样的技校生,比本科生都强,读懂人家代码后多动手写,要不很快忘掉的

一周热门 更多>