ARM寄存器指令总结
PINSEL0-0xE002C000-0x00000000(复位时默认为GPIO);
PINSEL1-0xE002C004-0x15400000(复位时,P0.27-30为AIN0-3);
PINSEL2-0xE002C014
复位时 地址线引脚功能的选择由BOOT[1:0]决定;
P2.31为AIN5;P2.30为AIN4;P3.28为AIN7;P3.29为AIN6;
不使能CS1 CS2 CS3 WE ;
是否使能跟踪端口由P1.20决定,是否使能调试端口由 P1.26决定。
配置一个引脚举例
P0.0为TXD0 PINSEL0 = (PINSEL0&0xfffffffc)|(0x01);
P0.0为GPIO PINSEL0 = (PINSEL0&0xfffffffc);
P0.0输出高 1
PINSEL0 = (PINSEL0&0xfffffffc); (先要配置为输出模式)
IO0DIR = IO0DIR|0x00000001; (写入1,输出,写入0,输入)
IO0SET = 0x00000001; (写入1,输出1,写入0,无效)
P0.0输出低 0
PINSEL0 = PINSEL0&0xfffffffc;
IO0DIR = IO0DIR|0x00000001;
IO0CLR = 0x00000001; (写入1,输出0,写入0,无效)
读取一个引脚的值
bak = IO0PIN; (基本上很少用到)
2存储器映射控制
存储器映射控制用于改变从地址0x00000000开始的中断向量的映射,这就允许了运行在不同存储器空间的代码对中断进行控制。
MEMMAP-0xE01FC040-0x00000000
MAP[1:0]
00时:Boot装载程序模式(0x7FFFE000-0x7FFFE03C),中断向量重新映射;
01时;用户FLASH模式(0x00000000-0x0000003C),中断向量不重新映射;
10时:用户RAM模式(0x40000000-0x4000003C),中断向量从静态RAM映射;
11时:用户外部存储器模式(0x80000000-0x8000003C),中断向量从外部存储器映射。
芯 片复位时,MEMMAP=0,启动Boot,Boot检测P0.14口,判断是否进入ISP还是启动用户程序,若启动用户程序,则自动MEMMAP=1。 若用户程序需要随时更改异常向量表,可以将异常向量表(64字节)复制到片内RAM的0x40000000上,然后设置MEMMAP=2进行重新映 射,0x40000000上的向量表就可以更改。
程序清单如下:
...
uint8 i;
uint32 *cp1,*cp2;
extern void Reset(void);
cp1=(uint32)Reset;
cp2=uint32 * 0x40000000;
for(i=0;i<16;i++){*cp2++=*cp1++;}
MEMMAP = 2;
...
3外部中断控制与向量中断控制器
管脚 p0.1和p0.16 INT0; 管脚 p0.3和p0.14 INT1;
管脚 p0.7和p0.15 INT2; 管脚 p0.9,p0.20和p0.30 INT3;
外部中断标志寄存器EXTINT(0xE01FC140,复位时,无中断标志) ,对某位写入1(电平触发方式下,引脚无效时,该操作才有效),清除该位对应的中断号的中断标志;
外部中断唤醒寄存器EXTWAKEUP(0xE01FC144,复位时,不唤醒),对某位写入1,该中断可唤醒处理器;
外部中断方式寄存器EXTMODE (0xE01FC148,复位时,电平触发方式)和 外部中断极性寄存器EXTPOLAR (0xE01FC14C,复位时,低电平有效)
EXTMODE[0] + EXTPOLAR[0]位
00时,低电平有效(此时,如果有多个引脚为EINT0功能,则相“与”);
01时,高电平有效(此时,如果有多个引脚为EINT0功能,则相“或”);
10时,下降沿触发(此时,如果有多个引脚为EINT0功能,则选端口号最低的引脚);
11时,上升沿触发(此时,如果有多个引脚为EINT0功能,则选端口号最低的引脚)。
多个引脚选为同一INT功能是,可通过IO0PIN和IO1PIN的值来判断产生该中断的引脚!
外部中断程序示例:
1初始化EINT0为低电平中断 引脚p0.16
PINSEL1 = (PINSEL1&0xfffffffc)|0x01; (P0.16选择INT功能)
EXTMODE = EXTMODE & 0X0E;
EXTPOLAR = EXTPOLAR & 0X0E;
2初始化EINT0为下降沿触发 引脚P0.16
PINSEL1 = (PINSEL1 & 0xfffffffc)|0x01;
EXTMODE = EXTMODE | 0x01;
EXTPOLAR = EXTPOLAR & 0x0E;
3 清除INT0中断标志
EXTINT = EXTINT | 0X01;
向量中断控制器(VIC)
VIC具有32个中断请求输入,16个向量IRQ中断,16个优先级(可动态分配),可产生软中断。
(1)快速中断请求(FIQ)具有最高的优先级。当只有一个中断被分配为FIQ中断时,可实现最短的FIQ等待时间;如果请求多于1个,VIC将中断请求相“或”,向ARM产生FIQ信号;
(2)向量IRQ具有slot0-slot15(最低的优先级)共16个优先级,32个请求中可分配16,它的中断优先级只是在同时产生多个中断时,VIC会将最高优先级请求的IRQ服务程序地址存入向量地址寄存器(VICVectAddr);
(3)非向量IRQ的优先级最低,且如果分配给它的中断多于1个,默认中断服务程序要从VIC中读取IRQ状态寄存器来识别产生中断请求的IRQ中断源是哪一个。
VIC将IRQ+非向量IRQ中断 相“或”,来产生IRQ信号。IRQ发出请求时,VIC提供 IRQ服务程序的地址,即VICVectAddr里的值。
VICSoftInt -0xFFFFF018-0 软件中断寄存器
写入1,强制产生与该位相关的中断
VICSoftIntClear-0xFFFFF01C-0 软件中断清零寄存器
写入1,强制清除软件中断寄存器的相应位,并强制解除中断 (只写)
VICRawIntr -0xFFFFF008-0 所有中断的状态寄存器,不管是否使能
某位为1,表示对应位的中断请求或软件中断声明 (只读)
VICIntEnable-0xFFFFF010-0 中断使能寄存器
写入1,使能中断请求或软件中断,写入0,无效。读该寄存器,为1时,表示IRQ或FIQ。
VICIntEnClr -0xFFFFF014-0 中断使能清零寄存器
写入1,清零中断使能寄存器中的对应位,并清除中断请求;写入0,无效(只写)
VICIntSelect-0xFFFFF00C-0 中断选择寄存器,分配为FIQ或IRQ
1,对应的中断分配为FIQ,0,对应的中断分配为IRQ;(读写)
VICIRQStatus-0xFFFFF000-0 IRQ状态寄存器,读出使能的IRQ的状态
1 对应的中断请求使能,并分配为 IRQ。(只读)
VICFIQStatus-0xFFFFF004-0 FIQ状态寄存器,读出使能的FIQ的状态
1 对应的中断请求使能,并分配为 FIQ。(只读)
VICVectCntl0 -0xFFFFF200-0 向量控制0寄存器
... ... ...
VICVectCntl15 -0xFFFFF23C-0 向量控制15寄存器
在VICVectCnt中禁止一个向量IRQ不会禁止中断本身,只是中断变为了非向量的形式;
bit5 为1,向量IRQ使能,当分配的中断请求或软件中断使能,被分配为IRQ并声明时,可产生一个唯一的ISR地址(读VICVectAddr寄存器)
bit4-0,分配给此向量IRQslot的中断请求或软件中断的编号。 (读写)
VICVectAddr0 -0xFFFFF100-0 向量地址0寄存器
... ... ...
VICVectAddr15 -0xFFFFF13C-0 向量地址15寄存器
16个向量IRQsolt中断服务程序地址。(读写)
VICDefVectAddr -0xFFFFF034-0 默认向量地址寄存器
当一个IRQ服务程序读取向量地址寄存器,并且没有IRQ响应时,则返回该寄存器的地址。 (读写)
VICVectAddr -0xFFFFF030-0 向量地址寄存器
当发生一个IRQ中断时,VIC会将对应的IRQ服务程序地址存入该寄存器,IRQ中断入口处的程序可读取该寄存器并跳转到读出的地址,执行相应的
中断服务程序。
注意:该寄存器应该在ISR快结束时执行一次写操作(写入的值一般为0),以便更新优先级硬件。
VICProtection -0xFFFFF020-0 保护使能寄存器
bit0 为1,VIC只能在特权模式下访问,为0,可以在用户或特权模式下访问。
中断源
0 WDT 1 保留给软件中断 2 ARM内核 3 ARM内核 4 定时器0 5 定时器1
6 UART0 7 UART1 8 PWM0 9 I2C 10 SPI0 11 SPI1
12 PLL 13 RTC 14 EINT0 15 EINT1 16 EINT2 17 EINT3 18 AD
#define Fcclk (Fosc * 4)
#define Fpclk (Fcclk / 4) * 1
1) 写 PLLCFG和 PLLCON:启动 PLL,但是不连接 PLL到系统内核。
PLLCON = 0x01 //PLLE = 1,PLLC = 0
PLLCFG = 0x04 //假定 Fosc=10MHZ,Fcclk=40MHZ计算
2) 保存中断寄存器,关中断
3) 连续写 PLLSEED(必须连续,不能被中断)
PLLSEED = 0xAA
PLLSEED = 0x55
4) 查询 PLLSTAT一直到 PLOCK=1
While((PLLSTART & 0x40) == 0);//等待,一直到 PLOCK=1
5) 写 PLLCFG和 PLLCON:启动 PLL,连接 PLL到系统内核。
PLLCON = 0x03 //PLLE = 1,PLLC = 1
PLLCFG = 0x04 //假定 Fosc=10MHZ,Fcclk=40MHZ计算
6) 连续写 PLLSEED(必须连续,不能被中断)
PLLSEED = 0xAA
PLLSEED = 0x55
7) 查询 PLLSTAT,等待 PLOCK=1,PLLE=1,PLLC=1,MSEL4:1和 PSEL1:0(PLLSTAT的位 6-5)
看是否完全符合,如果符合执行下一步,不符合报错。
8) 恢复原来的中断寄存器状态
}
1 存储器加速模块
存储器加速模块MAM是将下一个需要的ARM指令锁存起来,以防止CPU取指暂停。
MAM所用的方法是将FLASH存储器分成两组,每一组都可以独立进行访问 ,这两个FLASH组都有自己的预取指缓冲区和分支跟踪缓冲区(每次获取128位指令行)。若关闭MAM,所有存储器请求都会直接对FLASH操作。
MAMCR -0xE01FC000-0 存储器加速器模块控制寄存器
Bit0-1 00时,MAM被禁止;01时,部分功能使能;10时,完全使能,11保留
Bit2-7保留
MAMTIM -0xE01FC004-0x07 存储器加速器定时控制
Bit0-2 000时,保留;001-111 MAM取指周期分别为1-7个处理器时钟。
Bit3-7 保留
程序示例:
/*设置存储器加速模块*/
MAMCR = 0; //要先关闭,才能设置。
if( Fcclk < 20000000 )
{
MAMTIM = 1;
}
Else if( Fcclk < 40000000 )
{
MAMTIM = 2;
}
Else
{
MAMTIM = 3;
}
MAMCR = 2;
2 外部存储器控制
4个存储器组 bank0-bank3,片选信号分别为CS0-CS3;每个16MB空间;为AMBA AHB总线上的从设备。地址输出线 A[23:0],地址位A25,A24用于4个存储器组的译码。数据线为D[31:0]。OE输出使能信号,低有效。BLS[3:0]输出字节定位选择信号,低有效。WE 输出,写使能信号,低有效。
外部存储器的地址范围:
BANK0 80000000 – 80FFFFFF BCFG0 CS0
BANK1 81000000 – 81FFFFFF BCFG1 CS1
BANK2 82000000 – 82FFFFFF BCFG2 CS2
BANK3 83000000 – 83FFFFFF BCFG3 CS3
寄存器描述
BCFG0 -0xFFE00000-0x2000FBEF 存储器组0的配置寄存器
BCFG1 -0xFFE00004-0x2000FBEF 存储器组1的配置寄存器
BCFG2 -0xFFE00008-0x2000FBEF 存储器组2的配置寄存器
BCFG3 -0xFFE0000C-0x2000FBEF 存储器组3的配置寄存器
每个位的定义看手册吧,太多了。。。
启动代码中的总线的初始化设置,程序清单:
LDR R0, =PINSEL2
IF :DEF: EN_CRP ;选择芯片是否加密
LDR R1, =0x0f814910
ELSE
LDR R1, =0x0f814914
ENDIF
;0x0f814914
;保留位0000 ;地址线 A23-0 11111 ;使能P2.31,P2.30,P2.29和P2.28 000;保留位00 ;01 使能CS3;使能CS2 01; ? 0;保留 0;使能CS1 1;保留 00;使能WE 1;使能P3.28,P3.29 00; 01 ?;0100 调试。
STR R1, [R0]
LDR R0, =BCFG0
LDR R1, =0x1000ffef
STR R1, [R0]
;0x1000ffef
;0001 16位,0000 不是BRUST ROM,不写保护,
;0000 0000 保留 11111 WST2 1 RBLE 11111 WST1
;0 保留 1111 IDCY
3 UART控制
U0RBR -0xE000C000 接收器缓存寄存器(RO)
如果要访问U0RBR,U0LCR的DLAB 必须为0;
U0THR -0xE000C000 发送器保存寄存器 (WO)
如果要访问U0THR,U0LCR的DLAB 必须为0;
U0IER -0xE000C004-0中断使能寄存器
Bit0 RBR(RDA+CTI)中断使能 为1 使能,为0禁止。
Bit1 THRE中断使能 为1 使能,为0禁止。
Bit2 Rx线状态中断使能为1 使能,为0禁止。
Bit3-7 保留
如果要访问U0IER,U0LCR的DLAB 必须为0;
U0DLL 0xE000C000-0x01 除数锁存LSB寄存器
U0DLM 0xE000C004-0 除数锁存MSB寄存器
这两个寄存器一次构成一个16位的除数,用于产生波特率。
要访问他们,U0LCR的DLAB 必须为1;
UXDLMUXDLL = Fpclk/16/baud
U0IIR 0xE000C008-0x01 中断标志寄存器(RO)
Bit0 中断挂起,0时,有中断被挂起; 1时,无中断被挂起。
Bit1-3 中断标志,011 RLS 010 RDA 110 CTI 001 THRE.
Bit4-5 保留
Bit6-7 FIFO使能,等效于U0FCRDE bit0。
在退出中断服务程序前,必须读U0IIR来清除中断。
U0FCR 0xE000C008-0 FIFO控制寄存器
Bit0 FIFO使能,置位才能实现正确的UART0操作,该位的任何变化都降清空FIFO
Bit1 Rx FIFO复位,该位置位会自动清零RXFIFO,并该位自动清零
Bit2 Tx FIFO复位,该位置位会自动清零TXFIFO,并该位自动清零
Bit3-5 保留
Bit6-7 RX触发选择,00 触发点0,1字节,01,4字节,10,8字节,11,14字节。
U0LCR 0xE000C00C-0 线控制寄存器
Bit0-1 字长度选择 00 5位 01 6位 10 7位 11 8位
Bit2 停止位选择 0 时 1停止位 1时 2停止位
Bit3 奇偶使能 0 禁止奇偶产生和校验 1 使能
Bit4-5 奇偶选择 00 奇数 01 偶数 10 强制为1 11 强制为0;
Bit6 间隔控制 0 禁止间隔发送 1 使能间隔发送
Bit7 除数锁存访问位 0 禁止访问除数锁存寄存器 1 使能
U0LSR 0xE000C014-0 线状态寄存器
Bit0 接收数据就绪RDR 0时,U0RBR为空, 1时,包含有效数据
Bit1 溢出错误OE 0时,溢出错误状态未激活,1时,溢出错误状态激活
Bit2 奇偶错误PE 0时,奇偶错误状态未激活,1时,奇偶错误状态激活
Bit3 帧错误PE 0时,帧错误状态未激活,1时,帧错误状态激活
Bit4 奇偶错误PE 0时,奇偶错误状态未激活,1时,奇偶错误状态激活
Bit5 发送保存寄存器THRE空 0时,U0THR包含有效数据 1时,为空
Bit6 发送器TEMT空 0时,U0THR或U0TSR包含有效数据 1时,为空
Bit7 RXFIF0错误 0时,无错误, 1时,有RX错误
U0SCR 0xE000C01C-0 高速缓存寄存器???
程序代码示例:
1 UART0 初始化:
#define UART_BPS 115200 // 定义通讯波特率
void UART0_Init(void)
{
uint16 Fdiv;
U0LCR = 0x83; // DLAB = 1,可设置波特率
Fdiv = (Fpclk / 16) / UART_BPS; // 设置波特率
U0DLM = Fdiv / 256;
U0DLL = Fdiv % 256;
U0LCR = 0x03;
}
2 查询方式发送数据
void UART0_SendByte(uint8 data)
{
U0THR = data; // 发送数据
while( (U0LSR&0x40)==0 ); // 等待数据发送完毕
}
3查询方式接收数据
Uint8 UART0_RevByte(void)
{
Uint8 rcv_data;
While((U0LSR&0X01)==0);
Rcv_data = U0RBR;
Return (rcv_data);
}
4 包含中断的初始化(开接收中断)
/* 定义串口模式设置数据结构 */
typedef struct UartMode
{
uint8 datab; // 字长度,5/6/7/8可选
uint8 stopb; // 停止位,1/2可选
uint8 parity; // 奇偶校验位,0-无校验,1-奇校验,2-偶校验
}UARTMODE;
uint8 rcv_buf[8]; // UART0数据接收缓冲区
volatile uint8 rcv_new; // 接收新数据标志
*********************************************************************
** 函数名称:UART0_Init()
** 函数功能:串口初始化,设置工作模式和波特率。
** 入口参数:baud 波特率
** set 模式设置(UARTMODE数据结构)
** 出口参数:1-初始化成功, 0-初始化失败
*********************************************************************
int8 UART0_Init (uint32 baud, UARTMODE set)
{
uint32 bak;
/* 参数过滤 */
if ((baud ==0 ) || (baud > 115200)) return (0);
if ((set.datab <5) || (set.datab > 8)) return (0);
if ((set.stopb == 0) || (set.stopb > 2)) return (0);
if (set.parity > 4) return (0);
/* 设置串口波特率 */
U0LCR = 0x80; // DLAB = 1
bak = (Fpclk >> 4) / baud;
U0DLM = bak >> 8;
U0DLL = bak & 0xFF;
/* 设置串口模式 */
bak = set.datab - 5; // 设置字长
if (set.stopb == 2) bak |= 0x04; // 判断是否为2位停止位
if (set.parity != 0)
{
set.parity = set.parity - 1;
bak |= 0x08;
}
bak |= set.parity << 4; // 设置奇偶校验
U0LCR = bak;
return (1);
}
在主函数里面;
UARTMODE set;
set.datab = 8;
set.stopb = 1;
set.parity = 0;
rcv_new = 0;
PINSEL0 = 0x00000005; // 设置I/O连接到UART0
UART0_Init(115200, set); // 串口初始化
U0FCR = 0x81; // 使能FIFO,并设置触发点为8字节
U0IER = 0x01; // 允许RBR中断,即接收中断
/* 使能UART0中断 */
VICIntSelect = 0x00000000; // 设置所有的通道为IRQ中断
VICVectCntl1 = 0x20 | 0x06; // UART0分配到IRQ slot0,即最高优先级
VICVectAddr1 = (uint32)IRQ_UART0; // 设置UART0向量地址
VICIntEnable = 1 << 0x06; // 使能UART0中断
5 对应的接收中断处理函数
void __irq IRQ_UART0 (void)
{
uint8 i;
if ((U0IIR & 0x0F) == 0x04)
rcv_new = 1; // 设置接收到新的数据标志
for (i=0; i<8; i++)
{
rcv_buf[i] = U0RBR; // 读取FIFO的数据,并清除中断
}
VICVectAddr = 0x00; // 中断处理结束
}
4 I2C接口控制
I2C总线上存在以下两种类型的数据传输:
(1) 从主发送器向从接收器发送数据。主机发送的第一个字节是从机地址。接下来是数据字节流。从机每接收一个字节返回一个应答位。
(2) 从发送器向主接收器发送数据。第一个字节(从地址)由 主机发送。从机返回一个应答位。接下来从机向主机发送数据字节。主机每接收一个字节返回一个应答位。接收完最后一个字节,主机返回一个“非应答位”。主器 件产生所有串行时钟脉冲和起始以及停止条件。出现停止条件或重复的起始条件时传输结束。由于重复的起始条件同时是下一个串行发送的开始,因此I2C总线不会被释放。
I2C控制寄存器
I2CONSET I2C控制置位寄存器 读/置位 0 0xE001C000
Bit0-1 保留
Bit2 AA 应答标志, 写入1 置1
Bit3 SI I2C中断标志位, 写入1 置1
Bit4 STO 停止标志 写入1 置1
Bit5 STA 起始标志 写入1 置1
Bit6 I2EN I2C接口使能 写入1 置1
Bit7 保留
I2CONCLR I2C控制清零寄存器 只清零 NA 0xE001C018
Bit0-1 保留
Bit2 AAC 写入1 清I2CONSET对应位
Bit3 SIC 写入1清I2CONSET对应位
Bit4 保留
Bit5 STAC 写入1清I2CONSET对应位
Bit6 I2ENC 写入1清I2CONSET对应位
Bit7 保留
I2STAT I2C状态寄存器 只读 0xF8 0xE001C004
Bit0-2 这三个位总为0
Bit3-7 状态位(查手册,太多了)
I2DAT I2C数据寄存器 读/写 0 0xE001C008
包含发送和接收的数据,只能在SI置位的情况下访问
I2ADR I2C从地址寄存器 读/写 0 0xE001C00C
Bit0 GC 通用调用位 该位置位则通用调用地址00被识别
Bit1-7 地址 从模式地址
只能在从模式下使用
I2SCLH SCL占空比寄存器高半字 读/写 0x04 0xE001C010
SCL高电平保持的pclk周期数,必须大于4
I2SCLL SCL占空比寄存器低半字 读/写 0x04 0xE001C014
SCL低电平保持的pclk周期数,必须大于4
位频率/总线速率 = Fpclk/( I2SCLH+ I2SCLL)
要保证I2C通信速率在0-400khz。
4种操作模式:主发送器模式、主接收器模式、从发送器模式和从接收器模式。
主模式的配置
I2CONSET 必须配置为 I2EN 1 STA 0 STO 0 SI 0 AA 0;
主模式下初始化代码
void I2C_Init(uint32 fi2c)
{
if(fi2c>400000) fi2c = 400000;
PINSEL0 = (PINSEL0&0xFFFFFF0F) | 0x50; // 设置I2C控制口有效
I2SCLH = (Fpclk/fi2c + 1) / 2; // 设置I2C时钟为fi2c
I2SCLL = (Fpclk/fi2c) / 2;
I2CONCLR = 0x2C;
I2CONSET = 0x40; // 使能主I2C
/* 设置I2C中断允许 */
VICIntSelect = 0x00000000; // 设置所有通道为IRQ中断
VICVectCntl0 = 0x29; // I2C通道分配到IRQ slot 0,即优先级最高
VICVectAddr0 = (int)IRQ_I2C; // 设置I2C中断向量地址
VICIntEnable = 0x0200; // 使能I2C中断
}
主发送模式的格式:
S(起始位) + 从地址 + R(1)/W(0) + A + 数据 + A + 数据 + A/~A + P(停止位)
从模式的配置
I2CONSET 必须配置为 I2EN 1 STA 0 STO 0 SI 0 AA 1;
从模式下的初始化代码
void I2C_SlaveInit(uint8 addr)
{
PINSEL0 = (PINSEL0&0xFFFFFF0F) | 0x50; // 设置I2C控制口有效
I2ADR = adr&0xFE; //设置丛机地址
I2CONCLR = 0x28;
I2CONSET = 0x44; // 配置为丛机模式
/* 设置I2C中断允许 */
VICIntSelect = 0x00000000; // 设置所有通道为IRQ中断
VICVectCntl0 = 0x29; // I2C通道分配到IRQ slot 0,即优先级最高
VICVectAddr0 = (int)IRQ_I2C; // 设置I2C中断向量地址
VICIntEnable = 0x0200; // 使能I2C中断
}
从接收模式的格式:
S(起始位) + 从地址 + W(0) + A + 数据 + A + 数据 + ~A /A+ P(停止位)/RS
老说我的文章太长,唉,没办法,使劲删东西吧。
1 SPI接口控制
当器件为主机时,传输的起始由包含发送数据字节的主机来指示。此时,主机可激活时钟并开始传输。当传输的最后一个时钟周期结束时,传输结束。
当器件为从机并且 CPHA=0 时,传输在 SSEL 信号激活时开始,并在 SSEL 变为高电平时结束。当器件为从机且CPHA=1时,如果该器件被选择,传输从第一个时钟沿开始,并在数据采样的最后一个时钟沿
结束。
SPI 控制寄存器(S0SPCR - 0xE0020000)
在传输的最后一个周期置位。在从机模式下,该位在SCK的最后一个数据采样边沿置位。当第一次读取该寄存器时,该位清零。然后才能访问 SPI 数据寄存器。
注:SPIF不是SPI中断标志。中断标志位于SPINT寄存器中。
SPI 数据寄存器(S0SPDR - 0xE0020008)
处于主模式时,写该寄存器将启动SPI数据传输。从数据传输开始到SPIF状态
位置位并且还没有读取状态寄存器的这段时间内不能对该寄存器执行写操作。
SPI 时钟计数寄存器(S0SPCCR - 0xE002000C)
该寄存器的值必须为偶数。因此bit0必须为0。该寄存器的值还必须大于等于8。
SPI 速率可以这样进行计算:PCLK 速率/SPCCR 值。pclk 速率为 CCLK/VPB 除数。
SPI 中断寄存器(S0SPINT - 0xE002001C)
主机初始化程序示例
void mspi_ini(void)
{
S0PCCR = 0x52; // 设置SPI时钟分频
S0PCR = (0<<3)| //CPHA=0,数据在SCK的第一个时钟采样
(1<<4)| //CPOL=1,SCK低电平有效
(1<<5)| //MSTR=1,SPI处于主模式
(0<<6)| //LSBF=0,SPI数据传输MSB(bit7)在先
(0<<7); //SPIE=0,SPI中断禁止
}
丛机初始化程序示例
void SPI_Init(void)
{
S0PCR = (0 << 3)| // CPHA = 0, 数据在SCK 的第一个时钟沿采样
(1 << 4) | // CPOL = 1, SCK 为低有效
(0 << 5) | // MSTR = 0, SPI 处于从模式
(0 << 6) | // LSBF = 0, SPI 数据传输MSB (位7)在先
(1 << 7); // SPIE = 1, SPI 中断被使能
}
VICIntSelect = 0x00000000; // 设置所有中断为IRQ
VICVectCntl0 = (0x20 | 10); // SPI中断为最高优先级
VICVectAddr0 = (int32)SPI_IRQ; // 设置中断向量地址
VICIntEnable = (1 << 10); // 允许SPI中断
主机发送接收程序示例
unsigned char msend_data(unsigned char data)
{
IOCLR = CSN; // 片选
S0PDR = data;
while( 0==(S0PSR&0x80) ); // 等待SPIF置位,即等待数据发送完毕
IOSET = CSN;
return(S0PDR);
}
丛机接收程序示例,中断方式
volatile uint8 RcvData; // 接收到的数据
volatile uint8 RcvFlag; // 接收到新数据标志
void __irq SPI_IRQ(void)
{
uint32 tmp;
tmp = SPSR; // SPI读取数据寄存器之前,必须先读SPSR寄存器,清零SPIF位。
RcvData = SPDR; // 接收数据
RcvFlag = 0x01; // 接收到新数据
SPINT = 0x01; // 清除标志位
VICVectAddr = 0x00;
}
2 定时器控制
中断寄存器(IR: 定时器 0 - T0IR:0xE00040000;定时器 1 - T1IR:0xE0008000)
定时器控制寄存器(TCR: T0TCR:0xE0004004; T1TCR:0xE0008004)
定时器计数器(TC: T0TC:0xE0004008; T1TC:0xE0008008)
当预分频计数器到达计数的上限时,32 位定时器计数器加 1。如果 TC 在到达计数上限之前没有被复位,它将一直计数到0xFFFFFFFF然后翻转到0x00000000。
预分频寄存器(PR: T0PR:0xE000400C; T1PR:0xE000800C)
32位预分频寄存器指到预分频计数器的最大值。
预分频计数器寄存器(PC: T0PC:0xE0004010; T1PC:0xE0008010)
预分频计数器使用某个常量来控制pclk的分频。这样可实现控制定时器分辨率和定时器溢出时间之间的关系。预分频计数器每个 pclk 周期加 1。当其到达预分频寄存器中保存的值时,定时器计数器加 1,预分频计数器在下个 pclk 周期复位。这样,当 PR=0 时,定时器计数器每个 pclk 周期加 1,当 PR=1 时,定时器计数器每2个pclk周期加1。
匹配寄存器(MR0 - MR3)复位值 0
匹配寄存器值连续与定时器计数值相比较。当两个值相等时自动触发相应动作。这些动作包括产生中断,复位定时器计数器或停止定时器。
匹配控制寄存器(MCR: T0MCR:0xE0004014; T1MCR:0xE00080014)
捕获寄存器(CR0 - CR3)
每个捕获寄存器都与一个器件管脚相关联。当管脚发生特定的事件时,可将定时器计数值装入该寄存器。捕获控制寄存器的设定决定捕获功能是否使能以及捕获事件在管脚的上升沿、下降沿或是双边沿发生。
捕获控制寄存器(CCR: T0CCR:0xE0004028; T1CCR:0xE0008028)
查手册吧,太多了。。。。
外部匹配寄存器(EMR: T0EMR:0xE000403C; T1EMR:0xE0008003C)
外部匹配寄存器提供外部匹配管脚M(0-3)的控制和状态。具体查手册,手册。
看几个程序代码吧
(1)定时器0匹配产生中断
void Timer0Init(void)
{
T0TCR = 0x02; /* 定时器0复位 */
T0PR = 0; /* 不设时钟分频 */
T0MCR = 0x03; /* 匹配后复位TC,并产生中断 */
T0MR0 = Fpclk / 2; /* 设置0.5秒匹配值 */
T0IR = 0x01; /* 清除中断标志 */
T0TCR = 0x01; /* 启动定时器0 */
}
/* * 设置向量中断控制器 */
VICIntSelect = VICIntSelect & (~(1 << 4)); /* 定时器0分配为IRQ中断 */
VICVectCntl0 = 0x20 | 4; /* 定时器0分配为向量IRQ通道0 */
VICVectAddr0 = (uint32) Timer0ISR; /* 分配中断服务程序地址 */
VICIntEnable = 1 << 4; /* 定时器0中断使能 */
void __irq Timer0ISR (void)
{
T0IR = 0x01; /* 清除中断标志 */
VICVectAddr = 0x00; /* 中断向量结束 */
}
(2)定时器1匹配输出示例
void Timer1Init(void)
{
T1TCR = 0x02; /* 定时器1复位 */
T1PR = 0; /* 不设时钟分频 */
T1MCR = 0x02; /* 设置T1MR1匹配后复位T1TC */
T1EMR = 0x03 << 8; /* 匹配翻转 */
T1MR0 = Fpclk / 2; /* 设置0.5秒匹配值 */
T1IR = 0x01; /* 清除中断标志 */
T1TCR = 0x01; /* 启动定时器1 */
}
PINSEL1 = PINSEL1 & (0x03 << 6) ; /* 选择MAT1.2输出 */
PINSEL1 = PINSEL1 | (0x02 << 6); /* 选择MAT1.2输出 */
(3)定时器1PWM输出示例
void Timer1Init(void)
{
T1TCR = 0x02; /* 定时器0复位 */
T1PR = 0; /* 不设时钟分频 */
PWM1CON = 0x0C; /* 使能PWM输出 */
T1MCR = 0x02; /* 设置T0MR0匹配后复位T0TC */
T1MR0 = Fpclk / 2000; /* 设置PWM输出的周期 */
T1MR2 = (Fpclk / 2000) / 2; /* 设置PWM1.2输出占空比为50% */
T1MR3 = ((Fpclk / 2000) / 4) * 3; /* 设置PWM1.3输出占空比为25% */
T1TCR = 0x01; /* 启动定时器0 */
}
PINSEL1 = (PINSEL1 & (~(0x03 << 6))) | (0x02 << 6); /* 选MAT1.输出 */ PINSEL1 = (PINSEL1 & (~(0x03 << 8))) | (0x02 << 8); /* 选择MAT1.3输出 */
(4)定时器2捕获产生中断
void Timer2Init(void)
{
PINSEL1 = PINSEL1 & (~(0x03<<22)) | (0x02<<22); /* 选择CAP2.0功能 */
T2TCR = 0x02; /* 复位定时器2 */
T2IR = 0x10; /* 清除中断标志 */
T2CCR = 0x06; /* 设置上升沿捕获,并产生中断 */
T2TCR = 0x01; /* 启动定时器 */
}
/* * 设置向量中断控制器 */
VICIntSelect = VICIntSelect & (~(1 << 26)); /* 定时器2分配为IRQ中断*/
VICVectCntl0 = 0x20 | 26; /* 定时器2分配为向量IRQ通道0 */
VICVectAddr0 = (uint32) Timer2ISR; /* 分配中断服务程序地址 */
VICIntEnable = 1 << 26; /* 定时器2中断使能 */
void __irq Timer2ISR (void)
{
T2IR = 0x10; /* 清除中断标志 */
VICVectAddr = 0x00; /* 中断向量结束 */
}
3 AD控制
测量范围:0~3V ;10位转换时间>=2.44us ;10位逐次逼近式模数转换器。A/D 转换器的基本时钟由 VPB 时钟提供。可编程分频器可将时钟调整至逐步逼近转换所需的 4.5MHz(最大)。完全满足精度要求的转换需要11个这样的时钟
A/D 控制寄存器(ADCR – 0xE0034000)
具体自己查手册,太长了
A/D 数据寄存器(ADDR – 0xE0034004)
ADC初始化示例
PINSEL1 = 1 << 28; // P0.30连接到AD0.3
/* 进行ADC模块设置 */
AD0CR = (1 << 3) | // SEL=8,选择通道3
((Fpclk / 1000000 - 1) << 8) | // CLKDIV=Fpclk/1000000-1,转换时钟为1MHz
(0 << 16) | // BURST=0,软件控制转换操作
(0 << 17) | // CLKS=0, 使用11clock转换
(1 << 21) | // PDN=1,正常工作模式
(0 << 22) | // TEST1:0=00,正常工作模式
(1 << 24) | // START=1,直接启动ADC转换
(0 << 27); // 直接启动ADC转换时,此位无效
读取ADC数值
ADC_Data = (ADC_Data>>6) & 0x3FF; // 提取AD转换值
ADC_Data = ADC_Data * 3300; // 数值转换
ADC_Data = ADC_Data / 1024;
如果要使用中断
AD0CR = (1<<4) | // SEL=8,选择通道4
((Fpclk / 1000000 - 1) << 8) | // CLKDIV=Fpclk/1000000-1,转换时钟为1MHz
(0 << 16) | // BURST=0,软件控制转换操作
(0 << 17) | // CLKS=0, 使用11clock转换
(1 << 21) | // PDN=1,正常工作模式
(0 << 22) | // TEST1:0=00,正常工作模式
(3 << 24) | // START=3,P0.22管脚边沿启动AD转换
(1 << 27); // 下降沿
// 设置AD0中断IRQ
VICIntSelect = 0x00; // 所有中断通道设置为IRQ中断
VICVectCntl1 = 0x32; // AD0中断通道分配最高优先级(向量控制器0)
VICVectAddr1 = (uint32)ADC_Exception; // 设置中断服务程序地址向量
void __irq ADC_Exception(void)
{
x=AD0DR
VICVectAddr = 0x00; // 通知VIC中断处理结束
}
4 RTC控制
RTC 包含了许多寄存器。地址空间按照功能分成 4 个部分。前 8 个地址为混合寄存器组。第二部分的8个地址为定时器计数器组,第三部分的8个地址为报警寄存器组。最后一部分为基准时钟分频器。
混合寄存器组
中断位置(ILR - 0xE0024000)
0 RTCCIF 为1时,计数器增量中断模块产生中断。向该位写入1清除计数器增量中断。
1 RTCALF 为1时,报警寄存器产生中断。向该位写入1清除报警中断。
时钟节拍计数器(CTC - 0xE0024004)
0 保留
15:1时钟节拍计数器位于秒计数器之前,CTC 每秒计数 32768 个时钟。由于 RTC 预分频器的关系,这 32768 个时间增量的长度可能并不全部相同。
时钟控制寄存器(CCR - 0xE0024008)
0 CLKEN 时钟使能 当该位为1时,时间计数器使能。为0时,时间计数器都被禁止,这时可对其进行初始化。
1 CTCRST CTC 复位 为 1 时,时钟节拍计数器复位。在 CCR变为 0 之前,它将一直保持复位状态。
3:2 CTTEST 测试使能 在正常操作中,这些位应当全为0。
计数器增量中断寄存器位(CIIR - 0xE002400C)
计数器增量中断寄存器(CIIR)可使计数器每次增加时产生一次中断。在中断位置寄存器的位 0 (ILR[0])写入1之前,该中断一直保持有效。
报警屏蔽寄存器位(AMR - 0xE0024010)
完整时间寄存器 0(CTIME0 - 0xE0024014)完整时间寄存器0包含的时间值为:秒、分、小时和星期。
完整时间寄存器 1(CTIME1 - 0xE0024018)完整时间寄存器1包含的时间值为:日期(月)、月和年。
完整时间寄存器 2(CTIME2 - 0xE002401C)完整时间寄存器2仅包含日期(年)。
预分频整数寄存器(PREINT - 0xE0024080)预分频值的整数部分计算如下: PREINT = int (pclk/32768) – 1。PREINT的值必须大于等于1。
预分频小数寄存器(PREFRAC - 0xE0024084)预分频值的小数部分计算如下: PREFRAC = pclk – ((PREINT+1)×32768)
程序示例
void RTCInit(void)
{
PREINT = Fpclk / 32768 - 1; // 设置基准时钟分频器
PREFRAC = Fpclk - (Fpclk / 32768) * 32768;
YEAR = 2004; // 初化年
MONTH = 2; // 初化月
DOM = 19; // 初化日
HOUR = 8;
MIN = 30;
SEC = 0;
CIIR = 0x01; // 设置秒值的增量产生一次中断
CCR = 0x01; // 启动RTC
}
5 WDT控制
看门狗应当根据下面的方法来使用:
-在WDTC寄存器中设置看门狗定时器的固定装载值
-在WDMOD寄存器中设置模式
-通过向WDFEED寄存器顺序写入0xAA和0x55启动看门狗
-在看门狗向下溢出之前应当再次喂狗以防止复位/中断
可以检查看门狗超时标志(WDTOF)来确定看门狗是否产生复位条件。WDTOF标志必须由软件清零。
程序代码示例
WDTC = 11059200; // 设置WDTC,喂狗重装值
WDMOD = 0x03; // 复位并启动WDT
WDFEED = 0xAA;
WDFEED = 0x55;
浙公网安备 33010602011771号