回顾:
1.面试题:谈谈ARM裸板编程
1.1.一定要举例子说明即可,目前以开关LED为例
谈谈ARM裸板编程的思路
1.2.首先要分析用户需求(中心)
1.3.掌控LED硬件信息
粗看
位置
细看
原理图
表面看明确LED和CPU之间的硬件连接,本质目的要明白LED外设和CPU之间采用哪种硬件通信方式(LED采用GPIO)。
此时此刻画出一个简要的硬件连接操作示意图。
看图获取结论:CPU访问LED的流程
看手册时只关注跟自己需求相关的内容
看手册关键提取两点信息:
寄存器的基地址
寄存器的BIT位的含义
1.4.编写LED的裸板程序,明确裸板程序的框架
void abc(void)
{
xxx_init();
while(1) {
//做业务
}
}
根据框架,根据用户需求完成LED的程序
1.5.linux系统下的编译
...gcc
...ld
...objcopy
...objdump
1.6.利用网络进行下载调试
2.面试题:谈谈对串口UART的理解
2.1.交代计算中常见的几种硬件(CPU和外设)通信方式
GPIO/UART/I2C/SPI/1-Wire
我来谈谈UART,谈完以后可以再谈谈I2C/SPI等。
2.2.UART的定义
通用串行异步收发器
通用:普遍性 。
串行:一根数据线,1bit传输UART从低位开始 。
并行:多根数据线,多字节传输 。
串行和并行的对比:
距离
速度
抗干扰性
异步:明确:CPU的速度要远远快于外设, 势必考虑数据同步(发完还要确保接受正确) 。
数据同步方法:异步和同步
异步:在数据传输过程保证数据同步即可。
异步如何实现关键看协议,待我慢慢讲解UART协议,理解何为异步 。
同步:不仅仅需要数据线,还需要一根时钟控制信号线。
利用时钟控制信号线来实现双方的数据同步。很简单四个字:低放高取
此时此刻画出一个简要的操作示意图
例如:I2C总线和SPI总线就是采用同步
收发器:动态变化
2.3.UART串口的三种工作方式
1.单工
数据传输永远只能一个方向(要不发要不收)
2.半双工
数据传输可以两个方向(可以收也可以发,但不能同时进行)
3.全双工
数据传输可以同时双向进行
CPU和外设数据传输需要两根数据线
一根用于发送(TX),一根用于接受(RX)
别忘记还需要连接地线(GND)
此时此刻画出一个简要的硬件连接图
2.4.再次回顾之前的问题:
问:如何利用异步实现UART串口的数据同步呢?
答:在UART的数据传输协议中
问:UART的数据传输协议的内容是什么呢?
答:娓娓道来
1.首先交代一下UART协议相关的概念
空闲位:CPU和外设不再进行数据传输时,数据线上
一直发送空闲位,高电平(1)有效
起始位:CPU和外设进行数据传输时,首先在数据线上
要发送一个起始位信号,有效位数:1个bit位
低电平有效,类似:嗨,我要开始工作了
数据位:指定有效的数据位数,选择如下:5/6/7/8
一般选择为8位
奇偶校验位:指示数据传输时是否发生错误
有效的校验位数:1个bit位
对数据的校验方式有三种:
奇校验
偶校验
不校验:无需发送校验位
这里以CPU向BT发送0x95数据为例,采用奇校验方式检查数据传输是否发生错误
注意:CPU和BT必须都是奇校验方式!
发送端:CPU发送数据的过程
1.CPU首先将0x95通过TX数据线
发送给BT
2.CPU计算数据0x95中1的个数(4个)
结论:4本身是一个偶数
3.由于4是一个偶数,而数据校验
采用奇校验,所以CPU最后在发送一个
校验位,为高电平(1),这个1和4相加为5
5是奇数,满足奇校验
4.结论:校验位为高电平
接收端:BT接受数据并且判断数据是否正确
1.BT从TX上接收数据0x95
2.BT再从TX上接收CPU发送来的校验位(高电平1)
3.BT先算接收的数据0x95中1的个数为4
并且采用奇校验来验证,1的个数4和
校验位高电平相加符合奇校验
4.BT发现CPU发送的校验位满足
BT确认CPU发送的数据没有问题
停止位:指示数据传输结束
有效位数:1bit或者2bit
有效电平为高电平
类似:嗨,数据传输结束了
波特率:指示双方数据传输的速率
本质就是CPU和外设数据传输
指定一个步调!
波特率根据外设来指定!
例如:波特率为115200bps
表示一秒钟CPU和外设传输115200个bit位
问:虽然概念搞清楚,目前还是不清楚CPU如何
具体将某个数据通过TX数据线发送给外设?
答:务必举例子说明CPU和外设具体的传输过程
传输时序!
以CPU向BT发送0x95数据为例,并且UART
的工作参数为:115200, 8o1
具体传输过程如下:
1.CPU和BT不进行数据传输时,TX数据线
一直发送空闲位(高电平)
2.CPU开始向BT发送数据,首先向TX发送
起始位(1bit,低电平)
3.CPU继续向TX发送数据0x95(8bit,低位开始,
1->0->1->0->1->0->0->1)
4.CPU继续向TX发送校验位(1bit,高电平)
5.CPU继续向TX发送停止位(1bit,高电平)
至此数据发送完毕
6.最后CPU继续向TX发送空闲位(高电平)
7.切记切记切记:务必边说边画操作时序图(绝招)!
8.如果将来UART数据传输有异常,只需借助示波器
这个仪器抓取例如TX数据线上的波形,然后
分析抓取的波形图即可!
案例:画出UART的波形
传输的数据为:0x55
工作参数为:115200,8e2
2.5.实战演练UART的操作
1.提出一个需求:下位机通过UART0给上位机循环发送一个字符串,并且上位机能够显示接受的字符串信息 。
2.分析用户需求:下位机给上位机发送字符串"hello,world"。
3.掌控UART0串口的硬件信息
粗看:
UART0串口在下位机的位置
细看:
1.首先看UART0对应的原理图,结论:
硬件连接如下:
PC_RXD1->SP3232的R2IN->SP3232的R2OUT->S5P6818的UARTRXD0引脚
并且此引脚同样是复用的:
GPIOD14/UARTRXD0/ISO7816
结论:再次选择UARTRXD0功能(接收数据)
PC_TXD1->SP3232的T2OUT->SP3232的T2IN->S5P6818的UARTTXD0引脚
并且此引脚同样是复用的:
GPIO18/UARTTXD0/ISO7816/SDWP2
结论:这里选择为UARTTXD0(发送数据)
注意:SP3232E为一款电平转换芯片!
SP3232E能够将TTL电平转换为EIA电平
能够将EIA电平(串口线)转换为TTL电平(开发板上)
此时此刻画出一个简要的硬件连接示意图!参见uart2.bmp
此时此刻再画出一个CPU核访问操作UARTTXD0和UARTRXD0
的硬件操作示意图!参见uart3.bmp
看图得到结论:
1.CPU核通过地址指针的形式访问UART控制器
内部的一大堆寄存器,也就是CPU核通过软件
给UART控制器发送命令
2.UART控制器根据命令,硬件上自动
操作UARTTXD0和UARTRXD0这两个引脚
3.最终影响外设!
问:UART控制器和内部寄存器如何使用呢?
答:看S5P6818芯片手册,重点关注其中
UART控制器相关的章节!
2.打开S5P6818芯片手册P960
UART控制器相关的信息如下:
2.1.支持6路UART
每一个UART内部都有一个接收缓冲区
和发送缓冲区,大小为64字节
如果UART控制器工作在FIFO模式,缓冲区最大为64字节
如果UART控制器工作在非FIFO模式,缓冲区为1字节
此时此刻采用非FIFO模式!
2.2.UART控制器内部集成了发送器
而发送器内部又集成了发送缓冲区寄存器
和发送移位器:
CPU核发送数据的流程:
1.CPU核以指针的形式将数据放到发送缓冲区寄存器中进行缓存。
2.然后移位器硬件上自动从发送缓冲区中获取数据,然后将数据
一位一位的放到TX数据线上 。
3.移位器发送数据的频率由波特率产生器决定。
2.3.UART控制器内部还集成了接收器而接收器内部又集成了接收移位器和接收缓冲区。
CPU核接收数据的流程:
1.接收移位器硬件上自动从RX数据线上一位一位的将数据收集起来。
接收数据的频率又波特率产生器决定。
2.然后接收移位器硬件上自动将接收的数据放到接收缓冲区中
3.CPU核只需以地址指针的形式访问接收缓冲区寄存器即可,获取接收到的数据。
2.4.波特率配置P969
UBRDIVn和UFRACVALn两个寄存器的值共同决定着波特率的值;
公式:
UBRDIVn+UFRACVALn/16=(SCLK_UART/(bps*16))-1
假设SCLK_UART=40MHz=40000000,将来波特率为115200
得到:
UBRDIVn+UFRACVALn/16=(4000000/115200*16)-1
UBRDIVn+UFRACVALn/16=20.7
UBRDIVn=20(取整)
UFRACVALn=0.7*16(取整)=11
也就是说:如果将来SCLK_UART=40MHz
并且设置的波特率为115200,那么只需
向寄存器UBRDIVn写20,UFRACVALn写11即可
问:SCLK_UART是什么?
答:SCLK_UART为UART控制器的时钟源
3.UART控制器相关的寄存器P974
ULCON0:配置寄存器
基地址:0xC00A1000
BIT[1:0]=11 //设置数据位为8位
BIT[2]=0 //停止位为1位
BIT[5:3]=000 //不校验
BIT[6]=0 //普通的UART
UCON0:控制寄存器
基地址:0xC00A1004
注意:CPU访问外设的数据三种操作方式:
1.轮训方式(polling)
当CPU访问外设数据时,如果发现外设数据没有准备就绪,那么CPU就会原地忙等待(死等),直到外设准备好数据
2.中断方式(interrupt=IRQ=INT)
后续慢慢讲解
3.DMA方式
后续慢慢讲解
此时此刻,对UART的数据操作采用轮训方式!
BIT[3:0]=0101 //采用轮训方式
BIT[4]=0 //正常传输数据
BIT[5]=0 //正常传输
回环模式:自发自收,测试时常用
UTRSTAT0:状态寄存器
基地址:0xC00A1010
切记:CPU向发送缓冲区放数和从接受缓冲区读数的速度要远远快于发送移位器将数据放到TX和接受移位器从RX接收数据的速度!
BIT[0]=0:接收缓冲区为空
=1:接受缓冲区有有效数据
CPU判断是否准备就绪的代码:
while(!(UTRSTAT0 & 0x1));
//开始读取数据
BIT[1]=0:发送缓冲区中有数据
=1: 发送缓冲区为空
CPU判断数据是否发送完毕的代码:
while(!(UTRSTAT0 & 0x2));
//开始发下一个数据
UTXH0:发送缓冲区寄存器
基地址:0xC00A1020
BIT[7:0]=保存要发送的数据
URXH0:接受缓冲区寄存器
基地址:0xC00A1024
BIT[7:0]=保存接受到的数据
UBRDIV0:波特率配置寄存器你
基地址:0xC00A1028
根据公式进行换算
UFRACVAL0:波特率配置寄存器
基地址:0xC00A102C
根究公式进行换算
GPIODALTFN0(GPIOD14):GPIO复用功能选择寄存器
GPIODALTFN1(GPIOD18):GPIO复用功能选择寄存器
将GPIOD14/GPIOD18分别配置成UARTRXD0和UARTTXD0功能!
也就是将这两个引脚配置成UART专有的TX和RX引脚
问:SUART_CLK=40MHz从何而来?P305
答:SUART_CLK=CPU时钟/n
UART时钟配置相关寄存器P313:
UARTCLKENB:UART时钟使能寄存器
基地址:0xC00A9000
BIT[2]=1 //使能UART时钟
UARTCLKGEN0L:UART时钟配置寄存器
基地址:0xC00A9004
BIT[4:2]=000 UART时钟源为CPU的PLL[0]=800MHZ
//这里需要设置UART_CLK=50MHz
//UART_CLK=50MHZ=800MHZ/n
=>n=16=CLKDIV0+1=>CLKDIV0=15=0xF
得到:
BIT[12:5]=CLKDIV0=0xF;
至此:UART硬件信息掌控完毕!
4.编写UART裸板程序
参考代码:ftp://ARM/day04.rar/uart
1.面试题:谈谈ARM裸板编程
1.1.一定要举例子说明即可,目前以开关LED为例
谈谈ARM裸板编程的思路
1.2.首先要分析用户需求(中心)
1.3.掌控LED硬件信息
粗看
位置
细看
原理图
表面看明确LED和CPU之间的硬件连接,本质目的要明白LED外设和CPU之间采用哪种硬件通信方式(LED采用GPIO)。
此时此刻画出一个简要的硬件连接操作示意图。
看图获取结论:CPU访问LED的流程
看芯片手册
GPIO控制器集成在处理器内部,看处理器的芯片手册看手册时只关注跟自己需求相关的内容
看手册关键提取两点信息:
寄存器的基地址
寄存器的BIT位的含义
1.4.编写LED的裸板程序,明确裸板程序的框架
void abc(void)
{
xxx_init();
while(1) {
//做业务
}
}
根据框架,根据用户需求完成LED的程序
1.5.linux系统下的编译
...gcc
...ld
...objcopy
...objdump
1.6.利用网络进行下载调试
2.面试题:谈谈对串口UART的理解
2.1.交代计算中常见的几种硬件(CPU和外设)通信方式
GPIO/UART/I2C/SPI/1-Wire
我来谈谈UART,谈完以后可以再谈谈I2C/SPI等。
2.2.UART的定义
通用串行异步收发器
通用:普遍性 。
串行:一根数据线,1bit传输UART从低位开始 。
并行:多根数据线,多字节传输 。
串行和并行的对比:
距离
速度
抗干扰性
异步:明确:CPU的速度要远远快于外设, 势必考虑数据同步(发完还要确保接受正确) 。
数据同步方法:异步和同步
异步:在数据传输过程保证数据同步即可。
异步如何实现关键看协议,待我慢慢讲解UART协议,理解何为异步 。
同步:不仅仅需要数据线,还需要一根时钟控制信号线。
利用时钟控制信号线来实现双方的数据同步。很简单四个字:低放高取
此时此刻画出一个简要的操作示意图
例如:I2C总线和SPI总线就是采用同步
收发器:动态变化
2.3.UART串口的三种工作方式
1.单工
数据传输永远只能一个方向(要不发要不收)
2.半双工
数据传输可以两个方向(可以收也可以发,但不能同时进行)
3.全双工
数据传输可以同时双向进行
CPU和外设数据传输需要两根数据线
一根用于发送(TX),一根用于接受(RX)
别忘记还需要连接地线(GND)
此时此刻画出一个简要的硬件连接图
2.4.再次回顾之前的问题:
问:如何利用异步实现UART串口的数据同步呢?
答:在UART的数据传输协议中
问:UART的数据传输协议的内容是什么呢?
答:娓娓道来
1.首先交代一下UART协议相关的概念
空闲位:CPU和外设不再进行数据传输时,数据线上
一直发送空闲位,高电平(1)有效
起始位:CPU和外设进行数据传输时,首先在数据线上
要发送一个起始位信号,有效位数:1个bit位
低电平有效,类似:嗨,我要开始工作了
数据位:指定有效的数据位数,选择如下:5/6/7/8
一般选择为8位
奇偶校验位:指示数据传输时是否发生错误
有效的校验位数:1个bit位
对数据的校验方式有三种:
奇校验
偶校验
不校验:无需发送校验位
这里以CPU向BT发送0x95数据为例,采用奇校验方式检查数据传输是否发生错误
注意:CPU和BT必须都是奇校验方式!
发送端:CPU发送数据的过程
1.CPU首先将0x95通过TX数据线
发送给BT
2.CPU计算数据0x95中1的个数(4个)
结论:4本身是一个偶数
3.由于4是一个偶数,而数据校验
采用奇校验,所以CPU最后在发送一个
校验位,为高电平(1),这个1和4相加为5
5是奇数,满足奇校验
4.结论:校验位为高电平
接收端:BT接受数据并且判断数据是否正确
1.BT从TX上接收数据0x95
2.BT再从TX上接收CPU发送来的校验位(高电平1)
3.BT先算接收的数据0x95中1的个数为4
并且采用奇校验来验证,1的个数4和
校验位高电平相加符合奇校验
4.BT发现CPU发送的校验位满足
BT确认CPU发送的数据没有问题
停止位:指示数据传输结束
有效位数:1bit或者2bit
有效电平为高电平
类似:嗨,数据传输结束了
波特率:指示双方数据传输的速率
本质就是CPU和外设数据传输
指定一个步调!
波特率根据外设来指定!
例如:波特率为115200bps
表示一秒钟CPU和外设传输115200个bit位
问:虽然概念搞清楚,目前还是不清楚CPU如何
具体将某个数据通过TX数据线发送给外设?
答:务必举例子说明CPU和外设具体的传输过程
传输时序!
以CPU向BT发送0x95数据为例,并且UART
的工作参数为:115200, 8o1
具体传输过程如下:
1.CPU和BT不进行数据传输时,TX数据线
一直发送空闲位(高电平)
2.CPU开始向BT发送数据,首先向TX发送
起始位(1bit,低电平)
3.CPU继续向TX发送数据0x95(8bit,低位开始,
1->0->1->0->1->0->0->1)
4.CPU继续向TX发送校验位(1bit,高电平)
5.CPU继续向TX发送停止位(1bit,高电平)
至此数据发送完毕
6.最后CPU继续向TX发送空闲位(高电平)
7.切记切记切记:务必边说边画操作时序图(绝招)!
8.如果将来UART数据传输有异常,只需借助示波器
这个仪器抓取例如TX数据线上的波形,然后
分析抓取的波形图即可!
案例:画出UART的波形
传输的数据为:0x55
工作参数为:115200,8e2
2.5.实战演练UART的操作
1.提出一个需求:下位机通过UART0给上位机循环发送一个字符串,并且上位机能够显示接受的字符串信息 。
2.分析用户需求:下位机给上位机发送字符串"hello,world"。
结论:只需在下位机运行一个裸板程序。 此程序将字符串数据按照bit流通过TX这根数据线发送出去即可。
3.掌控UART0串口的硬件信息
粗看:
UART0串口在下位机的位置
细看:
1.首先看UART0对应的原理图,结论:
硬件连接如下:
PC_RXD1->SP3232的R2IN->SP3232的R2OUT->S5P6818的UARTRXD0引脚
并且此引脚同样是复用的:
GPIOD14/UARTRXD0/ISO7816
结论:再次选择UARTRXD0功能(接收数据)
PC_TXD1->SP3232的T2OUT->SP3232的T2IN->S5P6818的UARTTXD0引脚
并且此引脚同样是复用的:
GPIO18/UARTTXD0/ISO7816/SDWP2
结论:这里选择为UARTTXD0(发送数据)
注意:SP3232E为一款电平转换芯片!
SP3232E能够将TTL电平转换为EIA电平
能够将EIA电平(串口线)转换为TTL电平(开发板上)
此时此刻画出一个简要的硬件连接示意图!参见uart2.bmp
此时此刻再画出一个CPU核访问操作UARTTXD0和UARTRXD0
的硬件操作示意图!参见uart3.bmp
看图得到结论:
1.CPU核通过地址指针的形式访问UART控制器
内部的一大堆寄存器,也就是CPU核通过软件
给UART控制器发送命令
2.UART控制器根据命令,硬件上自动
操作UARTTXD0和UARTRXD0这两个引脚
3.最终影响外设!
问:UART控制器和内部寄存器如何使用呢?
答:看S5P6818芯片手册,重点关注其中
UART控制器相关的章节!
2.打开S5P6818芯片手册P960
UART控制器相关的信息如下:
2.1.支持6路UART
每一个UART内部都有一个接收缓冲区
和发送缓冲区,大小为64字节
如果UART控制器工作在FIFO模式,缓冲区最大为64字节
如果UART控制器工作在非FIFO模式,缓冲区为1字节
此时此刻采用非FIFO模式!
2.2.UART控制器内部集成了发送器
而发送器内部又集成了发送缓冲区寄存器
和发送移位器:
CPU核发送数据的流程:
1.CPU核以指针的形式将数据放到发送缓冲区寄存器中进行缓存。
2.然后移位器硬件上自动从发送缓冲区中获取数据,然后将数据
一位一位的放到TX数据线上 。
3.移位器发送数据的频率由波特率产生器决定。
2.3.UART控制器内部还集成了接收器而接收器内部又集成了接收移位器和接收缓冲区。
CPU核接收数据的流程:
1.接收移位器硬件上自动从RX数据线上一位一位的将数据收集起来。
接收数据的频率又波特率产生器决定。
2.然后接收移位器硬件上自动将接收的数据放到接收缓冲区中
3.CPU核只需以地址指针的形式访问接收缓冲区寄存器即可,获取接收到的数据。
2.4.波特率配置P969
UBRDIVn和UFRACVALn两个寄存器的值共同决定着波特率的值;
公式:
UBRDIVn+UFRACVALn/16=(SCLK_UART/(bps*16))-1
假设SCLK_UART=40MHz=40000000,将来波特率为115200
得到:
UBRDIVn+UFRACVALn/16=(4000000/115200*16)-1
UBRDIVn+UFRACVALn/16=20.7
UBRDIVn=20(取整)
UFRACVALn=0.7*16(取整)=11
也就是说:如果将来SCLK_UART=40MHz
并且设置的波特率为115200,那么只需
向寄存器UBRDIVn写20,UFRACVALn写11即可
问:SCLK_UART是什么?
答:SCLK_UART为UART控制器的时钟源
3.UART控制器相关的寄存器P974
ULCON0:配置寄存器
基地址:0xC00A1000
BIT[1:0]=11 //设置数据位为8位
BIT[2]=0 //停止位为1位
BIT[5:3]=000 //不校验
BIT[6]=0 //普通的UART
UCON0:控制寄存器
基地址:0xC00A1004
注意:CPU访问外设的数据三种操作方式:
1.轮训方式(polling)
当CPU访问外设数据时,如果发现外设数据没有准备就绪,那么CPU就会原地忙等待(死等),直到外设准备好数据
2.中断方式(interrupt=IRQ=INT)
后续慢慢讲解
3.DMA方式
后续慢慢讲解
此时此刻,对UART的数据操作采用轮训方式!
BIT[3:0]=0101 //采用轮训方式
BIT[4]=0 //正常传输数据
BIT[5]=0 //正常传输
回环模式:自发自收,测试时常用
UTRSTAT0:状态寄存器
基地址:0xC00A1010
切记:CPU向发送缓冲区放数和从接受缓冲区读数的速度要远远快于发送移位器将数据放到TX和接受移位器从RX接收数据的速度!
BIT[0]=0:接收缓冲区为空
=1:接受缓冲区有有效数据
CPU判断是否准备就绪的代码:
while(!(UTRSTAT0 & 0x1));
//开始读取数据
BIT[1]=0:发送缓冲区中有数据
=1: 发送缓冲区为空
CPU判断数据是否发送完毕的代码:
while(!(UTRSTAT0 & 0x2));
//开始发下一个数据
UTXH0:发送缓冲区寄存器
基地址:0xC00A1020
BIT[7:0]=保存要发送的数据
URXH0:接受缓冲区寄存器
基地址:0xC00A1024
BIT[7:0]=保存接受到的数据
UBRDIV0:波特率配置寄存器你
基地址:0xC00A1028
根据公式进行换算
UFRACVAL0:波特率配置寄存器
基地址:0xC00A102C
根究公式进行换算
GPIODALTFN0(GPIOD14):GPIO复用功能选择寄存器
GPIODALTFN1(GPIOD18):GPIO复用功能选择寄存器
将GPIOD14/GPIOD18分别配置成UARTRXD0和UARTTXD0功能!
也就是将这两个引脚配置成UART专有的TX和RX引脚
问:SUART_CLK=40MHz从何而来?P305
答:SUART_CLK=CPU时钟/n
UART时钟配置相关寄存器P313:
UARTCLKENB:UART时钟使能寄存器
基地址:0xC00A9000
BIT[2]=1 //使能UART时钟
UARTCLKGEN0L:UART时钟配置寄存器
基地址:0xC00A9004
BIT[4:2]=000 UART时钟源为CPU的PLL[0]=800MHZ
//这里需要设置UART_CLK=50MHz
//UART_CLK=50MHZ=800MHZ/n
=>n=16=CLKDIV0+1=>CLKDIV0=15=0xF
得到:
BIT[12:5]=CLKDIV0=0xF;
至此:UART硬件信息掌控完毕!
4.编写UART裸板程序
参考代码:ftp://ARM/day04.rar/uart