一、UART0/1初始化
教科书74页,给的是UART0初始化,考试考UART1

1. 配置引脚功能

GPA0CON寄存器的[7:4]和[3:0]要配置为0010
对应代码GPA0CON |= 0x22,0x22换算为10进制是0010 0010,对全是0的寄存器的0到7进行按位或,配置为0010 0010
如果是UART1的话,是配置CPA0CON的[19:16]和[23:20],需要把0x22左移16位
对应代码GPA0COn |= 0x22 << 4*4
2. 配置UART0/1参数
8位数据位、1位停止位、无校验、正常模式

对应代码ULCON0 = (0x3 << 0) | (0 << 2) | (0 << 3) | (0 << 6)
如果是UART1,对应代码就是把ULCON0换成ULCON1
3、配置UART0/1工作模式


中断或者polling模式、触发错误中断、时钟源PCLK
对应代码UCON0 = (1 << 0) | (1 << 2) | (1 << 6) | (0 << 10)
配置[1:0]和[3:2]都为01,把收发都配置为中断或者polling模式
如果是UART1,就把UCON0切换为UCON1。


禁止FIFO,对应代码UFCON0 = 0
4、计算波特率


PCLK时钟为66MHz,波特率115200,要计算UBRDIV0和UDIVSLOT0
这个12是怎么得到的:小数部分是0.8,12/16约等于0.8,故要找12对应的值
二、中断初始化


1. 配置中断引脚

把key1和key2对应的[3:0]和[7:4]都配置为1111
对应代码GPH0CON |= (0xFF << 0)(0xFF 对应 0b1111,1111)
如果是只配置key1或者key2:
- Key1:
GPH0CON |= (0x0F << 0) - Key2:
GPH0CON |= (0x0F << 4)
配置为下降沿触发:

下降沿触发即Falling edge triggered
对应代码
EXT_INT_0_CON |= 2:把[2:0]配置为0b010EXT_INT_0_CON |= (2 << 4): 把[6:4]配置为0b010
取消屏蔽外部中断

就是把第0位和第1位都配置为0
对应代码EXT_INT_0_MASK &= ~0x3把[1:0]通过按位与配置为0
2. 清中断挂起寄存器
封装为一个clear int pend函数

调用函数时将其置1
对应代码EXT_INT_0_PEND |= 0x3
3. 初始化中断控制器
选择中断类型:配置VIC0INTSELECT寄存器

配置两个引脚为IRQ模式,把[1:0]置0
VIC0INTSELECT &= ~0x3
清地址
VIC0ADDRESS = 0x0
设置中断服务程序入口地址:传入函数指针(函数地址)
VIC0VECTADDR0 = (int)IRQ_HandleVIC0VECTADDR1 = (int)IRQ_Handle
使能外部中断

将前两位置1: VIC0INTENABLE |= 0x3
4. 清除中断服务函数地址
封装为函数 clear int vectaddr
VIC0VECTADDR = 0x0
5. 读中断状态
获取VIC0IRQSTATUS寄存器的值
封装为函数get irqstatus,return VIC0IRQSTATUS
6. 中断服务函数IRQ_Handle
获取VIC0的状态
清中断向量寄存器
清中断挂起寄存器
三、Timer0/1初始化

目标是设置1s触发一次Timer0的中断
1. 设置定时器初始值和比较值寄存器
初始值寄存器TCNTB0对应Timer0,TCNTB1对应Timer1,决定输出信号频率
比较值寄存器TCMPB决定输出信号占空比
根据预分配系数和分频值来计算,预分频系数是65,分频系数是16,那么初始值寄存器的值就是66.7MHz/(65+1)/16=63162Hz
占空比为50%,那么比较值寄存器的值就是初始值*50%,即31581Hz
如果是1ms中断一次:

2. 设置预分配系数和分频值

Timer0的1/16分频,就是TCFG1 = 0x04,对应0100,如果是Timer1,则需要左移4位TCFG1 |= (0x04 << 4)
设置预分频系数TCFG0

设置为65:
- Timer0:
TCFG0 = 65 - Timer1: 左移4位:
TCFG0 = 65 << 4
3. 手动更新或者自动更新
配置自动加载寄存器TCON


这里直接把Timer对应的全部置1就行,例题有点不明所以
课后作业的答案里就是把Timer3对应的全部置1了
4. 使能中断

使能Timer3的中断:TINT_CSTAT |= 1 << 3;
四、定时器中断

1. 初始化中断控制器

选择中断类型为IRQ,课本截图中有错误,应该是按位与而非按位或
- Timer0对应第21位:
VIC0INTSELECT &= ~(1 << 21),通过按位与把第21位置0 - Timer1对应第22位:
VIC0INTSELECT &= ~(1 << 22),第22位置0
2. 清地址
VIC0ADDRESS = 0x0
3. 设置中断服务函数地址
VIC0VENCADDR21 = (int)IRQ_Handle,如果是Timer1,把21改成22
4. 使能中断
VIC0INTENABLE |= 1 << 21,把第21位置1,如果是Timer1,把21改成22
五、ADC初始化
课件PPT第63页

课件PPT第52页

1. 通过ADCMUX选择ADC通道

选择AIN1通道:ADCMUX = 0x1
2. 配置ADC控制寄存器TSADCCON
设置接入的触摸屏(0或者1)、设置ADC位数(10或者12)
我也不知道 1 << 14、49 << 6、0 << 2是为啥,就死记硬背吧
只知道 &= ~(1 << 16)是把第16位置0,设置为10位ADC,但是PPT里又没有这一项,很迷惑


3. ADC转换数据寄存器
为了获取ADC采样的数据,例如在定时器中断服务函数中读取
读取TSDATX0的数据:x = TSDATX0 & 0x3FF (10位ADC采样)
0x3FF是何意味,如果是12位ADC采样呢?
0x3FF是一个位掩码,表示只取低10位,其他位都清掉,12位的位掩码是0xFFF
// 10 位 ADC x = TSDATX0 & 0x3FF; // 取 0~1023
// 12 位 ADC x = TSDATX0 & 0xFFF; // 取 0~4095六、makefile/交叉编译工具链分析/start.S
示例:
led.bin: led.o start.o arm-linux-ld -Ttext 0xD0020010 -o key.elf $^ arm-linux-objcopy -O binary key.elf $@ arm-linux-objdump -D key.elf > key.dis
led.o: led.c arm-linux-gcc -c $< -o $@
start.o: start.S arm-linux-gcc -c $< -o $@
clean: rm *.o *.elf *.bin *.dis主要步骤:
- arm-linux-gcc编译依赖文件(.c和.S文件),生成.o目标文件
- arm-linux-ld 链接器,基于.o文件生成.elf文件,设置代码段地址为0xD0020010
- arm-linux-objcopy 复制elf文件并转换为bin文件