博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Contiki源码分析--CPU为cc253x里的uart0.c
阅读量:5265 次
发布时间:2019-06-14

本文共 5634 字,大约阅读时间需要 18 分钟。

我所使用的Contiki系统是contiki-sensinode。理解该文需要有cc2530里uart的相关知识,具体寄存器的用法不做介绍。

先放上所有代码,然后再仔细分析。

1 #include 
2 #include
3 4 #include "cc253x.h" 5 #include "sfr-bits.h" 6 #include "dev/uart0.h" 7 8 #if UART0_ENABLE 9 /*---------------------------------------------------------------------------*/10 void11 uart0_init()12 {13 #if UART0_CONF_HIGH_SPEED14 UART_SET_SPEED(0, UART_460_M, UART_460_E);15 #else16 UART_SET_SPEED(0, UART_115_M, UART_115_E);17 #endif18 19 #ifdef UART0_ALTERNATIVE_220 PERCFG |= PERCFG_U0CFG; / *alternative port 2 = P1.5-2 */21 #ifdef UART0_RTSCTS22 P1SEL |= 0x3C; /* peripheral select for TX and RX, RTS, CTS */23 #else24 P1SEL |= 0x30; /* peripheral select for TX and RX */25 P1 &= ~0x08; /* RTS down */26 #endif27 P1DIR |= 0x28; /* RTS, TX out */28 P1DIR &= ~0x14; /* CTS & RX in */29 #else30 PERCFG &= ~PERCFG_U0CFG; /* alternative port 1 = P0.5-2 */31 #ifdef UART0_RTSCTS32 P0SEL |= 0x20 | 0x10; /* peripheral select for TX and RX */33 #else34 P0SEL |= 0x0C; /* peripheral select for TX and RX */35 P0 &= ~0x20; /* RTS down */36 #endif37 P0DIR |= 0x28; /* RTS, TX out */38 P0DIR &= ~0x14; /* CTS, RX in */39 #endif40 41 42 #ifdef UART0_RTSCTS43 U0UCR = 0x42; /*defaults: 8N1, RTS/CTS, high stop bit*/44 #else45 U0UCR = 0x02; /*defaults: 8N1, no flow control, high stop bit*/46 #endif47 48 U0CSR = UCSR_MODE; /* UART mode */49 U0UCR |= 0x80; /* Flush */50 UART0_RX_EN();51 52 UART0_RX_INT(1);53 }54 /*---------------------------------------------------------------------------*/55 /* Write one byte over the UART. */56 void57 uart0_writeb(uint8_t byte)58 {59 UTX0IF = 0;60 U0DBUF = byte;61 while(!UTX0IF); /* Wait until byte has been transmitted. */62 UTX0IF = 0;63 }64 #endif

 

  • 首先是包含的头文件,就不多说了。
  • 然后是一个宏定义,#if UART0_ENABLE,若该宏未被定义,则uart0_init()不会被编译,节省内存空间。查看头文件:
1 /* UART0 Enable - Disable */2 #ifdef UART0_CONF_ENABLE3 #define UART0_ENABLE UART0_CONF_ENABLE4 #else5 #define UART0_ENABLE 06 #endif

发现UART0_CONF_ENABLE为真时,UART0_ENABLE也为真;否则UART0_ENABLE为0。再往上就没有找到UART0_CONF_ENABLE的定义了,可能需要自己定义。

  • 之后就是uart0_init()函数了,
1 #if UART0_CONF_HIGH_SPEED2   UART_SET_SPEED(0, UART_460_M, UART_460_E);3 #else4   UART_SET_SPEED(0, UART_115_M, UART_115_E);5 #endif

这是为了设置波特率,若定义的UART0_CONF_HIGH_SPEED为真,则设置的波特率大一些。查看宏定义:

#define UART_SET_SPEED(N, M, E) do{ U##N##BAUD = M; U##N##GCR = E; } while(0)

以上面第二行为例:变换结果为(“##”为连接符,把两边的字符相连)

1 do{ 2     U0BUAD = UART_460_M;3     U0GCR   = UART_460_E;4 }while(0);

继续跟踪宏定义:

1 /* 2000000 - cc2430 theoretical MAX when using the 32MHz clock */ 2 #define UART_2K_M      0 3 #define UART_2K_E     16 4 /* 1000000 - cc2430 theoretical MAX when using the 16MHz clock */ 5 #define UART_1K_M      0 6 #define UART_1K_E     15 7 /* 921600 */ 8 #define UART_921_M   216 9 #define UART_921_E    1410 /* 460800 Higher values lead to problems when the node needs to RX */11 #define UART_460_M   21612 #define UART_460_E    1313 /* 115200 */14 #define UART_115_M   21615 #define UART_115_E    1116 /* 38400 */17 #define UART_38_M     5918 #define UART_38_E     1019 /* 9600 */20 #define UART_9_M      5921 #define UART_9_E       8

最终的替换结果为,波特率查表为460800。

1 do{ 2     U0BUAD = 216;3     U0GCR   = 13;4 }while(0);
  • 继续往下看:
1 #ifdef UART0_ALTERNATIVE_2 2   PERCFG |= PERCFG_U0CFG;  / *alternative port 2 = P1.5-2 */ 3 #ifdef UART0_RTSCTS 4   P1SEL |= 0x3C;    /* peripheral select for TX and RX, RTS, CTS */ 5 #else 6   P1SEL |= 0x30;    /* peripheral select for TX and RX */ 7   P1 &= ~0x08;      /* RTS down */ 8 #endif 9   P1DIR |= 0x28;    /* RTS, TX out */10   P1DIR &= ~0x14;   /* CTS & RX in */

这个宏的条件是使用uart0的可变端口2,看下面的PERCFG |= 0x01(宏展开的值),uart0用备用位置2,根据后面信息知道端口为TX:P1_5,RX: P1_4。

至于注释里面的RTS和CTS我了解的不多,就管它。但是相应的uart0的TX和RX是知道了的。

假设上面那个宏条件失败,于是就到了这里:

1 #else 2   PERCFG &= ~PERCFG_U0CFG; /* alternative port 1 = P0.5-2 */ 3 #ifdef UART0_RTSCTS 4   P0SEL |= 0x20 | 0x10;    /* peripheral select for TX and RX */ 5 #else 6   P0SEL |= 0x0C;    /* peripheral select for TX and RX */ 7   P0 &= ~0x20;    /* RTS down */ 8 #endif 9   P0DIR |= 0x28;    /* RTS, TX out */10   P0DIR &= ~0x14;   /* CTS, RX in */11 #endif

这就是我们熟悉的cc2530里uart0的接口P0_2和P0_3。

首先设置PERCFG &= ~0x01; (宏展开的值),uart0的位置为备用位置1。下面那个宏UART0_RTSCTS没有看懂,就先不管它,假设该宏失败。

于是为P0SEL |= 0x0C; P0_2和P0_3都被选用了外设功能。   后面的P0 &= ~0x20我没管它。

之后P0DIR |= 0x28; P0DIR &= ~0x14;得知TX为P0_3,RX为P0_2。

  • 继续往下:
1 #ifdef UART0_RTSCTS2   U0UCR = 0x42; /*defaults: 8N1, RTS/CTS, high stop bit*/3 #else4   U0UCR = 0x02; /*defaults: 8N1, no flow control, high stop bit*/5 #endif

假设宏条件失败,其实这个条件在上面也出现过,若它为假,则初始化内容就是我们熟悉的cc2530里uart0的初始化。

U0UCR = 0x02;禁止硬件流,8位传输,无奇偶校验,1停止位,停止位高电平,起始位低电平。

  • 继续
1   U0CSR = UCSR_MODE; /* UART mode */2   U0UCR |= 0x80; /* Flush */3   UART0_RX_EN();4 5   UART0_RX_INT(1);

展开宏为

U0CSR = 0x80; /* UART mode */  U0UCR |= 0x80; /* Flush */  do {   U0CSR |= UCSR_RE; } while(0);  do { URX0IE = 1; } while(0);

继续展开

U0CSR = 0x80; /* UART mode */  U0UCR |= 0x80; /* Flush */  do {   U0CSR |= 0x40; } while(0);  do { URX0IE = 1; } while(0);

UART模式,接收器使能。设置FLASH为1,UART0读中断使能。

uart0_init()总算介绍完了,把各种不要的宏,以及宏展开就是如下结果:

1     U0BUAD = 216; 2     U0GCR   = 13; 3     PERCFG &= ~0x01; 4     P0SEL |= 0x0C; 5     P0DIR |= 0x28; 6     P0DIR &= ~0x14; 7     U0UCR = 0x02; 8     U0CSR = 0x80; 9     U0UCR |= 0x80;10     U0CSR |= 0x40;11     URX0IE = 1;

怎么样,是不是感觉很熟悉。

  • 后面还有一个uart0_writeb()写字节传输
voiduart0_writeb(uint8_t byte){  UTX0IF = 0;  U0DBUF = byte;  while(!UTX0IF); /* Wait until byte has been transmitted. */  UTX0IF = 0;}

这个就是cc2530里通过中断方式串口发送字节,就不解释了。

至此,uart0.c文件大致解释完毕,本人水平有限,有错误的地方希望指出,谢谢。

转载于:https://www.cnblogs.com/jackis-tang/p/11197168.html

你可能感兴趣的文章
nginx修改内核参数
查看>>
C 筛选法找素数
查看>>
TCP为什么需要3次握手与4次挥手(转载)
查看>>
IOC容器
查看>>
Windows 2003全面优化
查看>>
URAL 1002 Phone Numbers(KMP+最短路orDP)
查看>>
web_day4_css_宽度
查看>>
electron入门心得
查看>>
格而知之2:UIView的autoresizingMask属性探究
查看>>
我的Hook学习笔记
查看>>
js中的try/catch
查看>>
寄Android开发Gradle你需要知道的知识
查看>>
简述spring中常有的几种advice?
查看>>
整理推荐的CSS属性书写顺序
查看>>
ServerSocket和Socket通信
查看>>
css & input type & search icon
查看>>
源代码的下载和编译读后感
查看>>
Kafka学习笔记
查看>>
Octotree Chrome安装与使用方法
查看>>
Windows 环境下基于 Redis 的 Celery 任务调度模块的实现
查看>>