(基于ARM的)微机原理与接口技术笔记合集(7-14)
我是北航仪光低档垃圾暴毙货剑人,曾经是航C猪脚.咕了两个月,马上要烤期了,各位的破防水准备好了吗?现在是12月11号,再过3周就要考试了,之前一直想更新但是一直拖,但是再拖下去就暴毙了.现在我决定不继续拖了,于是有了这个合集,2个月来的R710F的上路历程.
首先是汇编语言杂记
(真的是笔记)如果配合ARM手册食用效果更佳.考试如果考一车汇编我必然挂科,不是开玩笑.



注意R710F是不带FPU的 所有的float和double都是软件处理.
R710F好像也没有硬件除法器......



汇编和C相互调用
ATPCS规定了:小于4个参数:寄存器r0
到r3
传参数
import CFunc
C调用汇编:使用export把程序段导出给C语言调用
比如说下面的汇编程序段要实现复制字符串的功能:

在C里面写个函数:
就可以调用上面的汇编程序了
嵌入式高级语言编程简介
像str71x.s
这样的汇编文件是启动代码()
不光r710f有启动代码 其他的板子,比如说树莓派pico(2个cortex-m0+核)或者stm32f103c8t6(1个cortex-m3核)都需要对应的启动文件,这个汇编文件和编译器相关.也有的编译器支持用C语言写启动文件.
启动代码需要做的:
建立栈区,堆区,向量表,硬件地址等,初始化C运行时
运行
main
函数捕获异常
r710f芯片大概结构(这个开发板的生产厂家现在好像已经寄了)
native总线:
FLASH
,SRAM
,调试口JTAG
,PRCCU
,
apb2总线(慢速):
模数转换ADC
,增强型中断控制器EIC
,定时器TIM
,实时时钟RTC
,外部中断XTI
,看门狗WDG
,3组GPIO
apb1总线:(快速)
2组IIC
,2组带缓冲区的SPI
,4组UART
,1个USB
,1个CAN
,1个HDLC

存储空间(对于别的板子,例如stm32,存储空间地址配置有差异.可以查手册获得这些信息)
r710f的地址范围:0x00000000
到0xffffffff
0x00000000
BOOT区
0x20000000
SRAM
r710fz2
64KB SRAM
0x40000000
FLASH
256KB Bank0
16KB Bank1
EMI 最大可以扩展4个16MB的FLASH(16位的)需要配置寄存器
0xa0000000
PRCCU(复位和时钟控制器)
0xc0000000
APB1外设
0xe0000000
APB2外设
0xfffffb00
R710F的启动模式

R710F供电模式和时钟
PRCCU
power,reset,clock control unit(供电,复位,时钟控制器)
对于CPU两个重要的事情:第一个是复位的状态一定要确定 第二个是时钟
RESET是复位到最初始的状态,是后面所有事情的基础.
上电复位,软件指令复位,看门狗复位
上电复位:RAM的东西不确定的
软件复位/看门狗复位:RAM的东西不丢失
CPU必会死机(躲不掉的).看门狗:一种硬件定时器,当核心死机了或者跑飞了复位.
上电和掉电的顺序很重要!
需要电源管理模块.可以做功耗管理,低功耗模式.
R710F集成2个稳压模块.只用3.3V供电就OK了

如果是电池供电,全速工作会非常费电.

R710F的时钟树(重点)

CK是时钟源(有源晶振)
选择时钟源用配置寄存器
32768无源晶振是低功耗时用的
USB有专用时钟

上手一个板子,理解时钟树很重要.R710F主频最大48MHz,引8MHz时钟源,过PLL(锁相环)倍频12分频2得48MHz,然后1分频给MCLK就是48MHz.如果是16MHz的时钟源就需要修改PLL配置寄存器,时序乱了CPU就不能正常工作.外设如果需要24M的时钟在PCLK处开2分频.
下面这个图是从CSDN搬的.STM32有4个时钟源,时钟树也更加复杂,但是顺着找顺着配置就能做出来开单片机必然先配置时钟,有的时候是人家SDK替你做了,自己做的时候需要看时钟树.

I/O接口技术简介
IO口的作用:解决速度匹配问题,信号转换,输入输出控制
CPU与IO之间信息:数据,状态信息,控制信息
IO口的编地址方式:统一编址(存储器映像),独立编址(有专门的指令访问外设)
GPIO的硬件结构
外设通过寄存器和处理器连接
寄存器组包括:配置寄存器(CFGR) 状态寄存器(SR) 数据寄存器(DR)
CPU与IO之间信息:数据,状态信息,控制信息
ARM对IO口进行了统一编址,不用I/O指令(通过ARM库的结构指针访问)
并行传输:一次传输多位(可以是一个数)需要多根线 用并口
并口速度快了可能有速度的微小差异(导致传输出错),干扰大
串行传输:一次传输一位(按顺序走) 用串口
80x86的外设有专门的指令去访问(不占存储空间)
GPIO功能:读引脚的高低电平/输出高低电平 切忌直接用GPIO接在电机等大电流器件上
配置IO口:一个GPIO有3个配置寄存器

8个模式:
输入:高阻(模拟)输入,TTL输入 CMOS输入 带上拉和下拉的输入(注意不是单独配置上拉和下拉)TTL和CMOS是检测1的电平不一样.AIN是模拟输入
输出:推拉输出/开漏输出(OUT模式或者复用模式)
下面是STM32的IO口结构(网上找的图,不放我手绘的了),和R710F的类似.但是
更复杂,有更舒适的库函数可以用,而且可以单独配置上拉或下拉.

串行接口
UART
: Universal Asynchronous Receiver Transmitter 通用异步收发器
串口 一次发一个bit 必须从bit0开始(LSBFIRST
)
和并行对应 并行可以一次可以发一个字节
USB
:Universal Serial Bus也是一种串行接口协议
高电平空闲,一般1个起始位,8个数据位(最常见的),[1个可选的校验位],1个(或2个)停止位
起始位低电平,然后是原始数据,校验位,停止位.
速度问题 baudrate
baudrate高的时候传输快,但是时钟偏差容易导致通信失败.
工业控制不能轻易的用蓝牙或WIFI因为不可靠,有可能丢帧
3.3V或5V的串口可以通过RS232模块转成大的电压 -12V(低) +12V(高)可以传输100米
为保证抗干扰 baudrate需要调低
常用于远程有线传输的还有RS485/RS422模块

R710F
的UART配置方式
配置 baudrate寄存器 baudrate=PCLK1/(16*BaudReg)
配置控制寄存器
缓冲寄存器(RX和TX)
CPU和外设之前的传送数据方式
1.无条件传送(点灯就是这样的)
外设简单,要求速度快/两次传送
需要buffer/latch
2.查询(轮询)方式
先查询再传送
至少2个端口(数据/状态)
3.中断方式
外设向CPU发中断(IRQ)->CPU中断当前工作进入IRQ函数->办完了返回
协调快速CPU和慢速外设
4.DMA方式
Direct Memory Access 直接从外设到存储器 省得CPU去搬砖 也可以外设搬到外设比如说把AD的结果搬到SPI
最先进的方式(硬件DMA) 用于大块数据传输/快速数据
需要CPU让开一些总线给DMA用 代价是CPU访问变慢
可以配合中断使用
使用流程:配置,传送,传送完了怎么办

中断技术
定义:CPU暂时中止当前的程序切换到中断处理程序(IRQHANDLER)
意义:CPU和IO并行工作,处理故障,提高实时性
中断系统:
早期的板子没有自带NVIC(nested vectored interrupt controller)
中断源:
分类:
按产生方式:强迫中断/非强迫中断
按中断位置:内部/外部
按进入handler方式:向量中断/非向量中断
中断优先级/中断嵌套:在中断处理函数里面可以再来中断,硬件处理(stm32或者树莓派pico的硬件NVIC/ r710f的EIC)
寄存器配置:查找datasheet
EIC把ARM7TDMI的2个中断(IRQ/FIQ)扩成32个中断
工作流程:EIC接受中断(ICR打开相应中断),更新IVR拼一个向量表
编程:初始化,配置,打开中断
设置IRQ中断优先级,打开中断,EIC负责配置
直接打开FIQ.在硬件上FIQ可以保证比IRQ优先处理

如何进入异常:
入口放跳转指令
b exception_handler
注意跳转范围限制文字池 32位的地址
ldr pc,=handler_addr
如何初始化 IVR和32个SIR
用地址初始化:缺点:32个子程的地址高16位必须相同
在EIC_IVR生成跳转指令
中断服务子程(ISR)是一种特殊的子程序
中断的步骤:
第一步:别的硬件发送中断请求

第三步:处理中断
保护现场(硬件可以做),保护断点(可能需要软件做,否则寄存器的关键数据变了,程序跑飞了)
开中断,处理,关中断,恢复现场.
哪些事情是硬件做或者SDK软件实现好了的,哪些是需要手写的 看不同的CPU和SDK手册
R710F的中断向量表:


向量表决定了FIQ可以打断IRQ
ARM7TDMI的异常(和中断有关,但是它们是两个概念)
直接异常:软中断/undefined instruction/预取指异常
间接异常:数据终止
外部产生的: RESET/IRQ/FIQ
RESET是最高级的 强制重开.

出现异常的时候R710F核心自动做的:

为什么是PC-4因为涉及流水线,设置PC为跳转到IRQ地址

R710F只有2个中断(IRQ和FIQ)通过EIC和XTI(外部中断控制器)实现中断的扩展
新一些的ARM Cortex-M板子普遍用核心自带的NVIC(nested vectored interrupt controller)处理中断

定时器(TIMER)


计数器:对谁计数 怎么变 复位?
R710F
的定时器16位
counter初始化为0xfffc
这点极不友好,重置就是0xfffc,不是任意的数

注:STM32是可以指定定时器重置后装载的数的,也能控制向上/向下计数,使用更加灵活,而且还有SYSTICK定时器可以用.
5个中断(溢出中断,2个比较中断,2个捕获中断)
输入->边沿检测电路ICAP变化,把计数器的值copy到ICAR/ICBR
可以测量引脚的脉冲宽度(PWM)太快的和太慢的都不能测.
输出引脚可以用于定时/中断,产生硬件PWM输出
OCAR用于控制脉宽:计数器与OCAR一致 OCMPA置OLVLA
OCBR用于控制周期:计数器与OCBR一致 OCMPA置OLVLB同时复位
OCAR<OCBR:PWM
OCAR=OCBR:方波
OCAR>OCBR:无输出

寄存器手册(纯寄存器开发要用,库函数开发可以不那么care)



r710F:板载12位ADC
输入0-2.5V 4个通道->4个寄存器(STM32f103c8t6和树莓派pico都是0-3.3V的AD模块)
可以出中断
配置时钟(PRESCALER=APB2FREQ/(SAMPLEFREQ*512*4))

配置过程:
模式:round robin(连续出多个)/single channel operation
初始化:
配置AD模块
ADC12_Init()
配置GPIO模拟输入
GPIO_Config(GPIO1,1,GPIO_HI_AIN_TRI)
配置prescaler(低7位有效)
ADC12_PrescalerConfig
配置转换模式
配置通道
轮询等待转换结果
取结果
关闭转换