我所使用的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. C# GC Finalizer IDispseable,.Net的垃圾回收机制

    1.GC只能回收堆里的托管资源 2.GC 回收,"代"的概念 .net 托管资源分三代,代数越大 资源的生命周期越长. 0 代 和1代的资源比较少可以比较频率的回收, 回收2代以上 ...

  2. Linux下C语言RPC(远程过程调用)编程实例

    在查看libc6-dev软件包提供的工具(用 dpkg -L libc6-dev 命令)的时候,发现此软件包提供了一个有用的工具rpcgen命令.通过rpcgen的man手册看到此工具的作用是把RPC ...

  3. Win8Metro(C#)数字图像处理--2.26图像减法

    原文:Win8Metro(C#)数字图像处理--2.26图像减法  [函数名称] 图像减法函数SubtractionProcess(WriteableBitmap src, WriteableBi ...

  4. 图像处理中的跨度(stride)

    原文:图像处理中的跨度(stride) 使用C#的BitmapData 最近要转开发平台,正研究C#.C#好是好,不过处理图片时一个像素一个像素的操作像素不是一般的慢.其实Delphi也一样,但好在D ...

  5. How to setup Assigned Access in Windows 10 (Kiosk Mode) 设置分配的访问权限(Kiosk模式)

    Let’s say you’re building some sort of ingenious mechanical contraption to be displayed in public th ...

  6. 给 Web 开发人员推荐的通用独立 UI 组件(二)

    现代 Web 开发在将体验和功能做到极致的同时,对于美观的追求也越来越高.在推荐完图形库之后,再来推荐一些精品的独立 UI 组件.这些组件可组合在一起,形成美观而交互强大的 Web UI . 给 We ...

  7. 教你如何快速使用Github

    以前看过几篇github的使用教程,感觉还是不是很清晰,自从看到了这篇,通俗易懂,也学会基本的使用了,在此为大家推荐.(转自知乎,为了能让更多的人看到,请允许我使用 “原创”,如果侵权请联系.) Gi ...

  8. Office Add-in Model 为 Outlook Mail Add-in 提供的 JavaScript API 介绍

    本文所讨论的 Mailbox API是指在 Mail Add-in 中可调用的 JavaScript API.开发者可以利用这些API 实现 Add-in 和 Outlook 的交互(数据读取与写入) ...

  9. log4j-slf4j 典型用例

    一.maven 配置 <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j ...

  10. Hadoop 3、Hadoop 分布式存储系统 HDFS(好多彩色图)

    HDFS是Hadoop Distribute File System 的简称,也就是Hadoop的一个分布式文件系统. 一.HDFS的优缺点 1.HDFS优点: a.高容错性 .数据保存多个副本 .数 ...