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

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

 #include <stdlib.h>
#include <string.h> #include "cc253x.h"
#include "sfr-bits.h"
#include "dev/uart0.h" #if UART0_ENABLE
/*---------------------------------------------------------------------------*/
void
uart0_init()
{
#if UART0_CONF_HIGH_SPEED
UART_SET_SPEED(, UART_460_M, UART_460_E);
#else
UART_SET_SPEED(, UART_115_M, UART_115_E);
#endif #ifdef UART0_ALTERNATIVE_2
PERCFG |= PERCFG_U0CFG; / *alternative port = P1.- */
#ifdef UART0_RTSCTS
P1SEL |= 0x3C; /* peripheral select for TX and RX, RTS, CTS */
#else
P1SEL |= 0x30; /* peripheral select for TX and RX */
P1 &= ~0x08; /* RTS down */
#endif
P1DIR |= 0x28; /* RTS, TX out */
P1DIR &= ~0x14; /* CTS & RX in */
#else
PERCFG &= ~PERCFG_U0CFG; /* alternative port 1 = P0.5-2 */
#ifdef UART0_RTSCTS
P0SEL |= 0x20 | 0x10; /* peripheral select for TX and RX */
#else
P0SEL |= 0x0C; /* peripheral select for TX and RX */
P0 &= ~0x20; /* RTS down */
#endif
P0DIR |= 0x28; /* RTS, TX out */
P0DIR &= ~0x14; /* CTS, RX in */
#endif #ifdef UART0_RTSCTS
U0UCR = 0x42; /*defaults: 8N1, RTS/CTS, high stop bit*/
#else
U0UCR = 0x02; /*defaults: 8N1, no flow control, high stop bit*/
#endif U0CSR = UCSR_MODE; /* UART mode */
U0UCR |= 0x80; /* Flush */
UART0_RX_EN(); UART0_RX_INT();
}
/*---------------------------------------------------------------------------*/
/* Write one byte over the UART. */
void
uart0_writeb(uint8_t byte)
{
UTX0IF = ;
U0DBUF = byte;
while(!UTX0IF); /* Wait until byte has been transmitted. */
UTX0IF = ;
}
#endif
  • 首先是包含的头文件,就不多说了。
  • 然后是一个宏定义,#if UART0_ENABLE,若该宏未被定义,则uart0_init()不会被编译,节省内存空间。查看头文件:
 /* UART0 Enable - Disable */
#ifdef UART0_CONF_ENABLE
#define UART0_ENABLE UART0_CONF_ENABLE
#else
#define UART0_ENABLE 0
#endif

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

  • 之后就是uart0_init()函数了,
 #if UART0_CONF_HIGH_SPEED
UART_SET_SPEED(, UART_460_M, UART_460_E);
#else
UART_SET_SPEED(, UART_115_M, UART_115_E);
#endif

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

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

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

 do{
U0BUAD = UART_460_M;
U0GCR = UART_460_E;
}while();

继续跟踪宏定义:

 /* 2000000 - cc2430 theoretical MAX when using the 32MHz clock */
#define UART_2K_M 0
#define UART_2K_E 16
/* 1000000 - cc2430 theoretical MAX when using the 16MHz clock */
#define UART_1K_M 0
#define UART_1K_E 15
/* 921600 */
#define UART_921_M 216
#define UART_921_E 14
/* 460800 Higher values lead to problems when the node needs to RX */
#define UART_460_M 216
#define UART_460_E 13
/* 115200 */
#define UART_115_M 216
#define UART_115_E 11
/* 38400 */
#define UART_38_M 59
#define UART_38_E 10
/* 9600 */
#define UART_9_M 59
#define UART_9_E 8

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

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

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

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

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

 #else
PERCFG &= ~PERCFG_U0CFG; /* alternative port 1 = P0.5-2 */
#ifdef UART0_RTSCTS
P0SEL |= 0x20 | 0x10; /* peripheral select for TX and RX */
#else
P0SEL |= 0x0C; /* peripheral select for TX and RX */
P0 &= ~0x20; /* RTS down */
#endif
P0DIR |= 0x28; /* RTS, TX out */
P0DIR &= ~0x14; /* CTS, RX in */
#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。

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

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

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

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

展开宏为

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

继续展开

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

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

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

     U0BUAD = ;
U0GCR = ;
PERCFG &= ~0x01;
P0SEL |= 0x0C;
P0DIR |= 0x28;
P0DIR &= ~0x14;
U0UCR = 0x02;
U0CSR = 0x80;
U0UCR |= 0x80;
U0CSR |= 0x40;
URX0IE = ;

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

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

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

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

Contiki源码分析--CPU为cc253x里的uart0.c的更多相关文章

  1. 鸿蒙内核源码分析(CPU篇) | 整个内核就是一个死循环 | 祝新的一年牛气冲天 ! | v32.02

    百篇博客系列篇.本篇为: v32.xx 鸿蒙内核源码分析(CPU篇) | 整个内核就是一个死循环 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度 ...

  2. spring源码分析-core.io包里面的类

    前些日子看<深入理解javaweb开发>时,看到第一章java的io流,发觉自己对io流真的不是很熟悉.然后看了下JDK1.7中io包的一点点代码,又看了org.springframewo ...

  3. 鸿蒙内核源码分析(线程概念篇) | 是谁在不停的折腾CPU? | 百篇博客分析OpenHarmony源码 | v21.06

    百篇博客系列篇.本篇为: v21.xx 鸿蒙内核源码分析(线程概念篇) | 是谁在不断的折腾CPU | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调 ...

  4. 鸿蒙内核源码分析(系统调用篇) | 开发者永远的口头禅 | 百篇博客分析OpenHarmony源码 | v37.03

    百篇博客系列篇.本篇为: v37.xx 鸿蒙内核源码分析(系统调用篇) | 开发者永远的口头禅 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度谁 ...

  5. 鸿蒙内核源码分析(并发并行篇) | 听过无数遍的两个概念 | 百篇博客分析OpenHarmony源码 | v25.01

    百篇博客系列篇.本篇为: v25.xx 鸿蒙内核源码分析(并发并行篇) | 听过无数遍的两个概念 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度 ...

  6. 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 百篇博客分析OpenHarmony源码 | v7.07

    百篇博客系列篇.本篇为: v07.xx 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调 ...

  7. 鸿蒙内核源码分析(调度队列篇) | 内核有多少个调度队列 | 百篇博客分析OpenHarmony源码 | v6.05

    百篇博客系列篇.本篇为: v06.xx 鸿蒙内核源码分析(调度队列篇) | 内核有多少个调度队列 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度 ...

  8. 鸿蒙内核源码分析(任务管理篇) | 任务池是如何管理的 | 百篇博客分析OpenHarmony源码 | v5.05

    百篇博客系列篇.本篇为: v05.xx 鸿蒙内核源码分析(任务管理篇) | 任务池是如何管理的 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度谁 ...

  9. 鸿蒙内核源码分析(任务调度篇) | 任务是内核调度的单元 | 百篇博客分析OpenHarmony源码 | v4.05

    百篇博客系列篇.本篇为: v04.xx 鸿蒙内核源码分析(任务调度篇) | 任务是内核调度的单元 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度 ...

随机推荐

  1. 关于Android 7.0更新后调用系统相机及电筒问题

    android升级到7.0后对权限又做了一个更新即不允许出现以file://的形式调用隐式APP,需要用共享文件的形式:content:// URI 因为系统相机是提供的共享 Provider , C ...

  2. android studio 3.0+发布签名apk注意的情况

    在build.gradle for module文件中添加 lintOptions { checkReleaseBuilds false abortOnError false } 这样避免失败

  3. 微信小程序把玩(二十二)action-sheet组件

    原文:微信小程序把玩(二十二)action-sheet组件 action-sheet组件是从底部弹出可选菜单项,估计也是借鉴IOS的设计添加的,action-sheet有两个子组件, action-s ...

  4. 个人博客链接英语MP3提示盗链

    今天想在wordpress博客中添加一个MP3进行播放,但是遇到了两个问题. 第一是页面无法正常加载播放器所需要的组件,获取资源返回404错误,查看之后发现时找不到wordpress中的一个svg文件 ...

  5. 轮廓追踪与C#实现

    原文:轮廓追踪与C#实现 轮廓追踪是图像处理中常见的方法,主要目的是追踪二值图像中目标物体的外轮廓,所得结果为单像素闭合轮廓. 流       程: 1. 确定种子点,即追踪的起始像素(如最左上方在轮 ...

  6. Delphi 10.2 Linux 程序开发环境部署的基本步骤(网络连接方式要选择桥接或者是Host Only)

    Delphi 10.2 Linux 程序开发环境部署的基本步骤 http://blog.qdac.cc/?p=4477 升級到 Delphi 10.2 Tokyo 笔记http://www.cnblo ...

  7. 实现Qt日志功能并输出到文件(使用qInstallMsgHandler安装customMessageHandler)good

    原文 http://www.cppblog.com/lauer3912/archive/2011/04/10/143870.html 一.基本分类:qDebug : 调试信息提示qWarning: 一 ...

  8. VS2013编译Qt5.6.0静态库,并提供了百度云下载(乌合之众)good

    获取qt5.6.0源码包 直接去www.qt.io下载就好了,这里就不详细说了. 这里是我已经编译好的** 链接:http://pan.baidu.com/s/1pLb6wVT 密码: ak7y ** ...

  9. OSGI资料

    http://osgi.codeplex.com/ http://www.iopenworks.com/

  10. python集合的内建函数

    s.issubset(t) 如果s 是t 的子集,则返回True,否则返回False s.issuperset(t) 如果t 是s 的超集,则返回True,否则返回False s.union(t) 返 ...