Chinaunix首页 | 论坛 | 博客
  • 博客访问: 276641
  • 博文数量: 60
  • 博客积分: 2501
  • 博客等级: 少校
  • 技术积分: 774
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-16 13:27
文章分类

全部博文(60)

文章存档

2011年(1)

2010年(1)

2009年(58)

我的朋友

分类: 嵌入式

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 - 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 - T0IR0xE00040000;定时器 1 - T1IR0xE0008000

 

定时器控制寄存器(TCR: T0TCR0xE0004004 T1TCR0xE0008004

 

定时器计数器(TC: T0TC0xE0004008 T1TC0xE0008008

当预分频计数器到达计数的上限时,32 位定时器计数器加 1。如果 TC 在到达计数上限之前没有被复位,它将一直计数到0xFFFFFFFF然后翻转到0x00000000

 

预分频寄存器(PR:  T0PR0xE000400C T1PR0xE000800C

32位预分频寄存器指到预分频计数器的最大值。

 

预分频计数器寄存器(PC:  T0PC0xE0004010 T1PC0xE0008010

预分频计数器使用某个常量来控制pclk的分频。这样可实现控制定时器分辨率和定时器溢出时间之间的关系。预分频计数器每个 pclk 周期加 1。当其到达预分频寄存器中保存的值时,定时器计数器加 1,预分频计数器在下个 pclk 周期复位。这样,当 PR=0 时,定时器计数器每个 pclk 周期加 1,当 PR=1 时,定时器计数器每2pclk周期加1

 

匹配寄存器(MR0 - MR3 复位值 0

匹配寄存器值连续与定时器计数值相比较。当两个值相等时自动触发相应动作。这些动作包括产生中断,复位定时器计数器或停止定时器。

 

匹配控制寄存器(MCR: T0MCR0xE0004014 T1MCR0xE00080014

 

捕获寄存器(CR0 - CR3

每个捕获寄存器都与一个器件管脚相关联。当管脚发生特定的事件时,可将定时器计数值装入该寄存器。捕获控制寄存器的设定决定捕获功能是否使能以及捕获事件在管脚的上升沿、下降沿或是双边沿发生。

 

捕获控制寄存器(CCR:  T0CCR0xE0004028 T1CCR0xE0008028

查手册吧,太多了。。。。

 

外部匹配寄存器(EMR: T0EMR0xE000403C T1EMR0xE0008003C

外部匹配寄存器提供外部匹配管脚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控制

测量范围:03V 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 

完整时间寄存器 0CTIME0 - 0xE0024014)完整时间寄存器0包含的时间值为:秒、分、小时和星期。

 

       完整时间寄存器 1CTIME1 - 0xE0024018)完整时间寄存器1包含的时间值为:日期(月) 、月和年。

      

       完整时间寄存器 2CTIME2 - 0xE002401C 完整时间寄存器2仅包含日期(年)

 

预分频整数寄存器(PREINT - 0xE0024080 预分频值的整数部分计算如下: PREINT = int (pclk/32768) 1PREINT的值必须大于等于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寄存器顺序写入0xAA0x55启动看门狗

在看门狗向下溢出之前应当再次喂狗以防止复位/中断

可以检查看门狗超时标志(WDTOF)来确定看门狗是否产生复位条件。WDTOF标志必须由软件清零。

 

 程序代码示例

    WDTC = 11059200;     // 设置WDTC,喂狗重装值
    WDMOD = 0x03;      // 复位并启动WDT

    WDFEED = 0xAA;
    WDFEED = 0x55;

 

 
阅读(4935) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~