分类: 嵌入式
2009-07-24 22:23:27
老说我的文章太长,唉,没办法,使劲删东西吧。
1 SPI接口控制
当器件为主机时,传输的起始由包含发送数据字节的主机来指示。此时,主机可激活时钟并开始传输。当传输的最后一个时钟周期结束时,传输结束。
当器件为从机并且 CPHA=0 时,传输在 SSEL 信号激活时开始,并在 SSEL 变为高电平时结束。当器件为从机且CPHA=1时,如果该器件被选择,传输从第一个时钟沿开始,并在数据采样的最后一个时钟沿
结束。
SPI 控制寄存器(S0SPCR - 0xE0020000)
在传输的最后一个周期置位。在从机模式下,该位在SCK的最后一个数据采样边沿置位。当第一次读取该寄存器时,该位清零。然后才能访问 SPI 数据寄存器。
注:SPIF不是SPI中断标志。中断标志位于SPINT寄存器中。
SPI 数据寄存器(S0SPDR - 0xE0020008)
处于主模式时,写该寄存器将启动SPI数据传输。从数据传输开始到SPIF状态
位置位并且还没有读取状态寄存器的这段时间内不能对该寄存器执行写操作。
SPI 时钟计数寄存器(S0SPCCR - 0xE
该寄存器的值必须为偶数。因此bit0必须为0。该寄存器的值还必须大于等于8。
SPI 速率可以这样进行计算:PCLK 速率/SPCCR 值。pclk 速率为 CCLK/VPB 除数。
SPI 中断寄存器(S0SPINT - 0xE
主机初始化程序示例
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:0xE
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:0xE
外部匹配寄存器提供外部匹配管脚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 = 0x
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 - 0xE
计数器增量中断寄存器(CIIR)可使计数器每次增加时产生一次中断。在中断位置寄存器的位 0 (ILR[0])写入1之前,该中断一直保持有效。
报警屏蔽寄存器位(AMR - 0xE0024010)
完整时间寄存器 0(CTIME0 - 0xE0024014)完整时间寄存器0包含的时间值为:秒、分、小时和星期。
完整时间寄存器 1(CTIME1 - 0xE0024018)完整时间寄存器1包含的时间值为:日期(月) 、月和年。
完整时间寄存器 2(CTIME2 - 0xE
预分频整数寄存器(PREINT - 0xE0024080) 预分频值的整数部分计算如下: PREINT = int (pclk/32768) – 1。PREINT的值必须大于等于1。
程序示例
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标志必须由软件清零。
WDMOD = 0x03; // 复位并启动WDT
WDFEED = 0x55;