class="markdown_views prism-dracula">
[笔记]|[stm32]|[寄存器存储器区别]|[PWM]|[串口]|[Timer]stm32f103笔记
此笔记为18.12.21笔者期末复习所写 ——仅作为自己期末复习以及过后查阅的资料
文章目录
单片机与嵌入式系统
单片机(英文缩写MCU )
单片机只是嵌入式CPU的称呼 (单片机可以理解为CPU)(嵌入式可有多个CPU)
单片机的特点是只有一个控制单元
嵌入式和普通的计算机核心区别在资源共享问题上
嵌入式可分为软件硬件组成
硬件 部分主要有以下组成:
以mpu 为核心的组成,如:arm等 。
以mcu 为核心,就是各种各样的单片机,它主要是因为把处理器和存储器等部件集成在一块芯片 上。
以dsp 为核心,主要用来处理语音图形 方面。
就是人们所说的sop 了。
而软件 部分主要是:
有的嵌入式有操作系统,有的没有。主要是由系统大小决定。
CPU、MCU、MPU、DSP的区别?
CPU :
CPU(Central Processing Unit,中央处理器 )发展出来三个分枝,一个是DSP (Digital Signal
Processing/Processor,数字信号处理 ),另外两个是MCU (Micro Control Unit,微控制器单元 )和MPU (Micro Processor Unit,微处理器单元 )。
MCU :
MCU集成了片上外围器件;MPU不带外围器件(例如存储器阵列),(MCU)是高度集成的通用结构的处理器 ,是去除了集成外设的MCU;DSP运算能力强 ,擅长很多的重复数据运算,而MCU则适合不同信息源的多种数据的处理诊断和运算,(MCU)侧重于控制 ,速度并不如DSP。
MCU区别于DSP的最大特点在于它的通用性 ,反映在指令集和寻址模式中。DSP与MCU的结合是DSC 。
单片机的基本工作原理
程序(命令的集合) -> 存储到
存储器 中(留下所分配的地址号) -> 使用时地址被取出 -> 被执行
单片机的几个重要概念
总线 :用于地址分配的线也较多(存储单元多),这些线被称为地址总线。
数据、地址、指令:都是‘0’和‘1’的组成的序列
功能复用,功能模块的初始化、驱动。
程序的执行过程。
开发环境的建立
stm32单片机简介
Cortex-M3内核
标准的ARM架构
高性能
低电压
低功耗
电压范围2.0到3.6V
I/O电压容限为5V
stm32程序编写基本步骤
初始化管脚
初始化功能模块
编写硬件测试代码
实现功能,调试,修改
嵌套中断向量控制器
嵌套中断向量控制器 (Nested Vector Interrupt Controller,简称
NVIC )它
为 基于
Cortex-M3 的微控制器提供了标准的
中断架构 和优秀的
中断响应能力 ,
为 超过240个
中断源提供专门的中断入口 ,而且可以赋予每个中断源单独的优先级。利用NVIC从可以达到极快的中断响应速度,
从收到中断请求到执行中断服务的第一条指令 仅需
12个周期 。这种极快的响应速度一方面得益于Cortex-M3内核对
堆栈 的自动处理机制,
这种机制是通过固化在CPU内部的微代码实现的 。另一方面,在中断请求连续出现的情况下,NVIC使用一种称为**“尾链”**的技术,
使连续而来的中断可以在6个时钟周期内得到服务 。在中断的压栈阶段,
更高优先级的中断可以不耗费任何额外的CPU周期就能完成嵌入低优先级中断的动作 。具体的细节后面我会继续总结的。
用户可以通过设置CPU自动进入低功耗状态,而使用中断来将其唤醒 ,CPU在中断时间来临之前会一直保持睡眠状态。
寄存器与存储器的区别
一般意义上理解,
寄存器是CPU里的存储单元 ,与CPU离得近,所以CPU在运算时通常都会用寄存器当中转站。
存储器是在CPU外部的存储器,分为RAM,ROM 。
对单片机来说,因为存储器,CPU都在一个片内,所以寄存器是片内RAM的一部分。
也就是说单片机的存储器包括寄存器
串行通讯
计算机通信:通信分为并行通信与串行通信两种基本方式。
并行通信 :将数据的各位用多条数据线同时进行传送,外加地址线和通信控制线。(多条数据线+地址线+通信控制线)
串行通信 :将数据分成1位1位的形式在一条传输线上逐个地传送 。
特殊的串行通讯:4位串行
并行通信和串行通信:
并行通信常用于集成电路芯片的内部 、同一插件板上各部件之间 、同一机箱内各插件板之间 的信息交互
串行通信常用于设备之间 的信息交互
同步通信和异步通信
根据数据传输方式的不同,可将串行通信分为同步通信和异步通信串行通信常用于设备之间 的信息交互
异步通信:若接收端与发送端使用的不是同一时钟信号(但必须同频率),则为异步通信。以字符为单位,一个字符一个字符地传送,并且 每一个字符要有起始符和停止符作为开始和结束的标志。(一个字符就是一帧) 。常见的是USART(串口)
同步通信是一种数据连续传输 的串行通信方式,通信时发送方把需要发送的多个字节数据和校验信息连接起来,组成数据块。发送时,发送方只需 在数据块前插入1~2个特殊的同步字符 ,然后按特定速率逐位输出(发送)数据块内的各位数据。接收方在接收到特定的同步字符后,也按相同速率接收数据块内的各位数据。(常见的有IIC,SPI 等)
串行通讯的工作方式
单工方式 :这种方式只允许数据按一个固定的方向传输 。数据传输仅能从发送设备传输到接收设备 。
半双工方式 :数据可以从A发送到B,也可以由B发送到A 。但A、B之间只有一根传输线 ,因此同一时刻只能作一个方向的传送 。其传送方向由收发控制开关K切换 。平时一般让A、B方都处于接收状态,以便能够随时响应对方的呼叫 。两个串行通信设备之间只有一条数据线,数据传输可以沿两个方向,但需要分时进行 。
全双工方式 :数据可同时在两个方向上传送 。
串口与RS232、RS485、RS422(属于物理层知识)
RS422是差分全双工(4线),RS232是双工(3线),RS485是半双工(2线)
波特率
单位:bps(bit per second)
定义:每秒钟传送的二进制位数 。
Baudrate(波特率范围):50 ~ 19200 ~ 57600
50,100,150,300,600,1200,2400,
4800,9600,19200,38400,57600,115200
如每秒传送240个字符,而每个字符格式包含10位这时的波特率为10位(bit)×240个/s = 2400 bit/s。
在异步串行通信中,接收方和发送方应使用相同的波特率,才能成功传送数据 。
STM32的串口
一般意义上我们所说的串口指的是USART 。SPI,IIC都会特别指出。
至少有3个串口 ,根据具体的型号有所不同。
1号串口可以下载程序用。
使用串口首先要使能IO时钟 ,串口模块时钟 ,初始化IO ,初始化串口 。
有关串口的高级使用:中断 ,串口重定向 。
调试手段
设置断点 ,设置断点的技巧:
在程序运行的代码中可以设置断点,程序运行到断点处即停止,但是断点处不见得就是问题出现的时刻。需要根据猜测设置需要进入的条件。
串口日志输出 :
在程序运行的过程中可以通过串口将运行过程中的一些关键变量输出以得知程序运行的状态是否正确。
通过外界输入一些信息,影响程序运行的状态,观察运行的输出以测试程序运行是否正常 。
中断
什么是“中断”?
CPU执行程序时,由于发生了某种随机的事件(外部或内部),引起CPU暂时中断正在运行的程序,转去执行一段特殊的服务程序(中断服务子程序或中断处理程序) ,以处理该事件,该事件处理完后又返回被中断的程序继续执行 ,这一过程称为中断。
EG:吃饭时突然手机铃响…
STM32中的优先级概念
STM32(Cortex-M3)中有两个优先级的概念:抢占式优先级 和响应优先级 ,也把响应优先级称作“亚优先级”或“副优先级” ,每个中断源都需要被指定这两种优先级。
何为占先式优先级(pre-emption priority)
高占先式优先级的中断事件会打断当前的主程序/中断程序运行—抢断式优先响应 ,俗称中断嵌套 。
何为副优先级(subpriority)
在占先式优先级相同的情况下,高副优先级的中断优先被响应 ;
在占先式优先级相同的情况下 ,如果有低副优先级中断正在执行,高副优先级的中断要等待已被响应的低副优先级中断执行结束后才能得到响应 —非抢断式响应(不能嵌套) 。
stm32中对中断优先级的定义
STM32中指定中断优先级的寄存器位有4位,这4个寄存器位的分组方式如下:
第0组:所有4位用于指定响应优先级
第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级
第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级
第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级
第4组:所有4位用于指定抢占式优先级
stm32的串口接收中断
步骤一:初始化GPIO
步骤二:开时钟
步骤三:初始化USART1
步骤四:编写中断函数
void USART1_IRQHandler(void)
八段码
八段码(数码管)的基本概念
stm32的八段码使用
步骤一:初始化GPIO
步骤二:开时钟
步骤三:初始化USART1
步骤四:编写中断函数 void USART1_IRQHandler(void)
步骤五: 找段
步骤六:换码
定时器
stm32的定时器
STM32一共有8个通用16位Timer ,其中TIMER1和TIMER8是高级定时器 ,其它的TIMER2~TIMER7是普通定时器 。
此外还有一个Systick(系统滴答定时器) ,这个定时器通常在操作系统中作为系统的任务切换周期 。
还有一个RTC ,是一个毫秒定时器 ,支持秒级中断 ,用来做实时时钟计数器 。
看门狗定时器 也可以算一个。
8个定时器中,Timer1和Timer8是由APB2(输出最高频率为72MHZ)预分频 后,再通过一个倍频器得到时钟频率,最高为72MHz 。Timer2~Timer7则是由APB1(输出最高频率为36MHZ)预分频 后,再通过一个倍频器得到时钟频率,最高为36MHz 。
Systick(系统滴答定时器)
void Delay_Init ( u8 SYSCLK)
{
SysTick-> CTRL & = ~ BIT ( 2 ) ;
SysTick-> CTRL & = ~ BIT ( 1 ) ;
fac_us = SYSCLK/ 8 ;
fac_ms = ( u16) fac_us* 1000 ;
}
void delay_us ( u32 nus)
{
SysTick-> LOAD = ( u32) fac_us* nus- 1 ;
SysTick-> VAL = 1 ;
SysTick-> CTRL | = BIT ( 0 ) ;
while ( ! ( SysTick-> CTRL& ( 1 << 16 ) ) ) ;
SysTick-> CTRL & = ~ BIT ( 0 ) ;
}
void Delay ( __IO uint32_t nTime)
{
TimingDelay = nTime;
while ( TimingDelay != 0 ) ;
}
systick也有中断入口也可以使用中断方式进行延时,具体代码可下自行研究。
stm32的通用定时器
TIM2-TIM5普通定时器的定时功能。
编程步骤
配置系统时钟;
配置NVIC;
配置GPIO;
配置TIMER;
配置:
(1) 利用TIM_DeInit()函数将Timer设置为默认缺省值;
(2) TIM_InternalClockConfig()选择TIMx来设置内部时钟源; //可省略
(3) TIM_Perscaler来设置预分频系数;
(4) TIM_ClockDivision来设置时钟分割;
(5) TIM_CounterMode来设置计数器模式;
(6) TIM_Period来设置自动装入的值
(7) TIM_ARRPerloadConfig()来设置是否使用预装载缓冲器 //可省略
(8) TIM_ITConfig()来开启TIMx的中断
其中(3)-(6)步骤中的参数由TIM_TimerBaseInitTypeDef结构体给出。步骤(3)中的预分频系数用来确定TIMx所使用的时钟频率,具体计算方法为:CK_INT/(TIM_Perscaler+1)。CK_INT是内部时钟源的频率,是根据2.1中所描述的APB1的倍频器送出的时钟,TIM_Perscaler是用户设定的预分频系数,其值范围是从0
– 65535。
步骤(7)中需要禁止使用预装载缓冲器。当预装载缓冲器被禁止时,写入自动装入的值(TIMx_ARR)的数值会直接传送到对应的影子寄存器;如果使能预加载寄存器,则写入ARR的数值会在更新事件时,才会从预加载寄存器传送到对应的影子寄存器。
stm32的TIM2初始化
void TIMER_cfg ( )
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd ( RCC_APB1Periph_TIM2, ENABLE) ;
TIM_DeInit ( TIM2) ;
TIM_TimeBaseStructure. TIM_Prescaler = 36000 - 1 ;
TIM_TimeBaseStructure. TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure. TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure. TIM_Period = 2000 - 1 ;
TIM_TimeBaseInit ( TIM2, & TIM_TimeBaseStructure) ;
TIM_ClearFlag ( TIM2, TIM_FLAG_Update) ;
TIM_ITConfig ( TIM2, TIM_IT_Update, ENABLE) ;
TIM_Cmd ( TIM2, ENABLE) ;
}
stm32的TIM2定时器中断函数
void NVIC_cfg ( )
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig ( NVIC_PriorityGroup_1) ;
NVIC_InitStructure. NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure. NVIC_IRQChannelPreemptionPriority = 0 ;
NVIC_InitStructure. NVIC_IRQChannelSubPriority = 0 ;
NVIC_InitStructure. NVIC_IRQChannelCmd = ENABLE;
NVIC_Init ( & NVIC_InitStructure) ;
}
void TIM2_IRQHandler ( void )
{
u8 ReadValue;
if ( TIM_GetITStatus ( TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit ( TIM2 , TIM_FLAG_Update) ;
ReadValue = GPIO_ReadOutputDataBit ( GPIOD, GPIO_Pin_13) ;
if ( ReadValue == 0 )
{
GPIO_SetBits ( GPIOD, GPIO_Pin_13) ;
}
else
{
GPIO_ResetBits ( GPIOD, GPIO_Pin_13) ;
}
}
}
通讯协议(串口)
通讯协议:
通信协议或简称为传输协议(Communications Protocol)在电信中,是指在任何物理介质中允许两个或多个在传输系统中的终端之间传播信息的系统标准,也是指 计算机通信或网络设备的共同语言 。[1], 通信协议定义了通信中的语法学, 语义学和同步规则以及可能存在的错误检测与纠正。通信协议在硬件,软件或两者之间皆可实现[2]为了交换大量信息,通信系统使用通用格式(协议)。每条信息都有明确的意义使得预定位置给予响应,并独立生效回馈指定行为,通信协议须参与实体都同意才能生效
通讯协议又称通信规程 ,是指通信双方对数据传送控制的一种约定。约定中包括对数据格式 ,同步方式 ,传送速度 ,传送步骤 ,检纠错方式 以及控制字符定义 等问题做出统一规定,通信双方必须共同遵守,它也叫做链路控制规程 。
通讯协议的要素:
包头
包尾
地址
解析
通讯协议处理设计思想
命令缓存区 buffer
分帧
命令处理
硬件pwm
硬件pwm基本原理
pwm由定时器产 ,定时器的定时时间决定了pwm的频率
比较寄存器 决定了pwm的占空比
(比较寄存器,作用是其中寄存了与计数寄存器相比较的值,当两个值相等时 ,发生一次比较跳变,输出的pwm波跳变 )
定时器与输出pwm的管脚之间是有约束关系的 。
pwm初始化
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA| RCC_APB2Periph_GPIOB| RCC_APB2Periph_T IM1, ENABLE) ;
GPIO_InitStructure2. GPIO_Pin= GPIO_Pin_8;
GPIO_InitStructure2. GPIO_Speed= GPIO_Speed_50MHz;
GPIO_InitStructure2. GPIO_Mode= GPIO_Mode_Out_PP;
GPIO_Init ( GPIOA, & GPIO_InitStructure2 GPIO_InitStructure2. GPIO_Pin= GPIO_Pin_13;
GPIO_InitStructure2. GPIO_Speed= GPIO_Speed_50MHz;
GPIO_InitStructure2. GPIO_Mode= GPIO_Mode_Out_PP;
GPIO_Init ( GPIOB, & GPIO_InitStructure2) ;
TIM_TimeBaseStructure. TIM_Period= 1000 - 1 ;
TIM_TimeBaseStructure. TIM_Prescaler= 72 - 1 ;
TIM_TimeBaseStructure. TIM_ClockDivision= TIM_CKD_DIV1;
TIM_TimeBaseStructure. TIM_CounterMode= TIM_CounterMode_Up;
TIM_TimeBaseStructure. TIM_RepetitionCounter= 0 ;
TIM_TimeBaseInit ( TIM1, & TIM_TimeBaseStructure) ;
TIM_OCInitStructure. TIM_OCMode= TIM_OCMode_PWM2;
TIM_OCInitStructure. TIM_Pulse= 500 ;
TIM_OCInitStructure. TIM_OCPolarity= TIM_OCPolarity_Low;
TIM_OCInitStructure. TIM_OutputState= TIM_OutputState_Enable;
TIM_OCInitStructure. TIM_OCNPolarity= TIM_OCNPolarity_High;
TIM_OCInitStructure. TIM_OutputNState= TIM_OutputNState_Enable;
TIM_OCInitStructure. TIM_OCIdleState= TIM_OCIdleState_Reset;
TIM_OCInitStructure. TIM_OCNIdleState= TIM_OCNIdleState_Reset;
TIM_OC1Init ( TIM1, & TIM_OCInitStructure) ;
TIM_BDTRInitStructure. TIM_OSSRState = TIM_OSSRState_Disable;
TIM_BDTRInitStructure. TIM_OSSIState = TIM_OSSIState_Disable;
TIM_BDTRInitStructure. TIM_LOCKLevel = TIM_LOCKLevel_OFF;
TIM_BDTRInitStructure. TIM_DeadTime = 0x90 ;
TIM_BDTRInitStructure. TIM_Break = TIM_Break_Disable;
TIM_BDTRInitStructure. TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM_BDTRInitStructure. TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig ( TIM1, & TIM_BDTRInitStructure) ;
TIM_OC1PreloadConfig ( TIM1, TIM_OCPreload_Enable) ;
TIM_ARRPreloadConfig ( TIM1, ENABLE) ;
TIM_Cmd ( TIM1, ENABLE) ;
TIM_CtrlPWMOutputs ( TIM1, ENABLE) ;
TIM_SetAutoreload ( TIM1, 1000 ) ;
TIM_SetCompare1 ( TIM1, 500 ) ;
TIM_CtrlPWMOutputs ( TIM1, ENABLE) ;
TIM_SetAutoreload ( TIM1, 1000 ) ;
TIM_SetCompare1 ( TIM1, 500 ) ;