CC2430 串口使用详解

http://blog.csdn.net/xukai871105/article/details/7303584

为了完成课题,最近下定决心学习CC2430。网上的资料很多,重复的部分不做过多的介绍,没有的部分做一下少许的补充,希望对大家有用!【建议各位使用更新的CC2530,该芯片为CC2430的替代版本】

全部代码如下,先看一下整体!

[cpp]  view plain copy
  1. <span style="font-size:16px;">//头文件  
  2. #include "hal.h"  
  3. #include "stdio.h"  
  4. // 函数声明  
  5. UINT8 UART0_Init();  
  6.   
  7. void main(){  
  8.     //使用外部时钟  
  9.      SET_MAIN_CLOCK_SOURCE(CRYSTAL);  
  10.     //串口初始化  
  11.      UART0_Init();  
  12.     //字符输出 输出1  
  13.     putchar('1');  
  14.     //字符串输出 输出Hello CC2430  
  15.     printf("Hello CC2430!\n");  
  16.     while(1){  
  17.    }  
  18. }  
  19.   
  20. int putchar(int c){  
  21.     if(c== '\n'){  
  22.       while(!UTX0IF);  
  23.       UTX0IF = 0;  
  24.       U0DBUF = '\r';  
  25.     }  
  26.     while(!UTX0IF);  
  27.     UTX0IF = 0;  
  28.     U0DBUF = c;  
  29.       return c;  
  30. }  
  31.   
  32. UINT8 UART0_Init(){  
  33.     //UART0 IO口定位  
  34.     IO_PER_LOC_UART0_AT_PORT0_PIN2345();  
  35.     //9600 8 N 1  
  36.    UART_SETUP(0,9600,HIGH_STOP);  
  37.    UTX0IF = 1;  
  38.    return 0;  
  39. }</span>  

下面一步一步分析一下

1      头文件

#include "hal.h" 该头文件包括了操作CC2430常用寄存器的宏,书中找到的觉得很实用。

#include "stdio.h" 调用printf函数,重定义putchar函数

2    定义系统时钟 SET_MAIN_CLOCK_SOURCE(CRYSTAL);   

       设定了CC2430的时钟频率,即使用片外32MHz。根据数据手册,CC2430可以有两种时钟,第一种是片外的32M石英晶振,另一种是片内的16M的RC振荡器。顺便说一下,这个SET_MAIN_CLOCK_SOURCE() 是一个名为hal.h文件中的“动作宏”。我手头有一本书,名为《ZigBee技术实践教程》,其中的代码都使用了这个头文件。该头文件中有很多的API函数,若仔细的查看代码,配合数据手册页可以看懂其中各宏的“原理”。设定时钟的的函数原型是这样的:

[cpp]  view plain copy
  1. <span style="font-size:16px;">#define SET_MAIN_CLOCK_SOURCE(source) \  
  2.    do {                               \  
  3.       if(source) {                    \  
  4.         CLKCON |= 0x40;               \  
  5.         while(!HIGH_FREQUENCY_RC_OSC_STABLE); \  
  6.         if(TICKSPD == 0){             \  
  7.           CLKCON |= 0x08;             \  
  8.         }                             \  
  9.         SLEEP |= 0x04;                \  
  10.       }                               \  
  11.       else {                          \  
  12.         SLEEP &= ~0x04;               \  
  13.         while(!XOSC_STABLE);          \  
  14.         asm("NOP");                   \  
  15.         CLKCON &= ~0x47;              \  
  16.         SLEEP |= 0x04;                \  
  17.       }                               \  
  18.    }while (0)  
  19.   
  20.   
  21. </span>  

对应着数据手册,完全可以看懂其中的“玄机”。由于我还处在学习CC2430的初级阶段,以后就根据这个头文件编写程序。至于寄存器的话,大概知道其中的作用即可

       领悟到的小技巧:

       1 如果需要使用一个复杂的动作宏的话,多行书写使用 \ 。

       2 所有的这些动作都包含在 do{} while(0)中。

3    定义IO口IO_PER_LOC_UART0_AT_PORT0_PIN2345();

       这句话把UART0的IO口定义到P02 P03 P04 P05。函数原型是这样的:

[cpp]  view plain copy
  1. <span style="font-size:16px;">#define IO_PER_LOC_UART0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x00; } while (0)</span>  

4   设定串口相关参数UART_SETUP(0,9600,HIGH_STOP);

      函数原型是这样的:

[cpp]  view plain copy
  1. <span style="font-size:16px;">#define UART_SETUP(uart, baudRate, options)      \  
  2.    do {                                          \  
  3.       if((uart) == 0){                           \  
  4.          if(PERCFG & 0x01){                      \  
  5.             P1SEL |= 0x30;                       \  
  6.          } else {                                \  
  7.             P0SEL |= 0x0C;                       \  
  8.          }                                       \  
  9.       }                                          \  
  10.       else {                                     \  
  11.          if(PERCFG & 0x02){                      \  
  12.             P1SEL |= 0xC0;                       \  
  13.          } else {                                \  
  14.             P0SEL |= 0x30;                       \  
  15.          }                                       \  
  16.       }                                          \  
  17.                                                  \  
  18.       U##uart##GCR = BAUD_E((baudRate),CLKSPD);  \  
  19.       U##uart##BAUD = BAUD_M(baudRate);          \  
  20.                                                  \  
  21.       U##uart##CSR |= 0x80;                      \  
  22.                                                  \  
  23.                                                  \  
  24.       U##uart##UCR |= ((options) | 0x80);        \  
  25.                                                  \  
  26.       if((options) & TRANSFER_MSB_FIRST){        \  
  27.          U##uart##GCR |= 0x20;                   \  
  28.       }                                          \  
  29.    } while(0)  
  30. </span>  


 

5   UTX0IF = 1; UART0发送完成标志位1

 

      若串口数据发送完成,该寄存器被置位。若寄存器被置位,需要通过软件清零。这个也是很好理解的。

 

6   putchar和printf函数

 

      说完了初始化,再来谈谈如何使用putchar和printf函数。Putchar和printf都是C语言标准库函数。Printf调用putchar实现字符数据的传送。翻看IAR的代码,获得了使用putchar函数的信息。IAR中来了一段51单片机的代码。该代码位于EW8051_CompilerReference文件中。其中有这么一段参考代码。

[cpp]  view plain copy
  1. #include <io8052.h>   
  2. int putchar(int c)  {   
  3. if (c == '\n') {   
  4. while (!SCON_bit.TI);   
  5. SCON_bit.TI = 0;   
  6. SBUF = 0x0d;   
  7. }   
  8. while (!SCON_bit.TI);   
  9. SCON_bit.TI = 0;   
  10. return (SBUF = c);   
  11. }  

      这段代码有点51基础的都可以看懂。唯一需要说明的就是,如果出现转义字符\n(回车)的话,先输出转义字符\t(换行)。简单说,windows喜欢先来换行(\r),再来回车(\n)。而linux中只要一个回车就OK。

   同理,CC2430的代码就是可以这样写:

[cpp]  view plain copy
  1. int putchar(int c){  
  2.     if(c== '\n'){  
  3.       while(!UTX0IF);  
  4.       UTX0IF = 0;  
  5.       U0DBUF = '\r';  
  6.     }  
  7.     while(!UTX0IF);  
  8.     UTX0IF = 0;  
  9.     U0DBUF = c;  
  10.       return c;  
  11. }  

 

7     IAR中printf参数设置

      接下来必须说说IAR中相关的设置,在EW8051_UserGuide中,指出了printf和scanf函数的相关设置。printf包含了small medium large三个选项。每个选型包含不同的printf功能,当然功能越全,消耗的资源也就越多。在这里我就先设置成small了。IAR的说明文件中也给出了这个选项参数所提供的功能,如下表所示。

CC2430 串口使用详解_第1张图片CC2430 串口使用详解_第2张图片

 

8    实验结果

最后给出实验的结果,虽然代码非常的简单,但是我还是花了一整个下午去调试,后来发现其实是IAR中的link中某参数选择错误了。实验的结果还是预想的那样,使用的时候还是要注意串口的参数设定,CC2430的串口调试助手的参数要一致。

CC2430 串口使用详解_第3张图片

 

总结

      串口的使用非常的重要,它是PC机和单片机的重要桥梁。现在,单片机负责采集数据,而PC机负责分析处理数据。在这个示例代码中,通过使用hal头文件,避免了复杂难记的寄存器操作,从而快速的初始化串口;通过改写putchar函数,写出了适合CC2430串口输出的函数;最后使用了标准的printf函数实现了串口输出。



你可能感兴趣的:(CC2430 串口使用详解)