Contiki源码分析--CPU为cc253x里的uart0.c
我所使用的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的更多相关文章
- 鸿蒙内核源码分析(CPU篇) | 整个内核就是一个死循环 | 祝新的一年牛气冲天 ! | v32.02
百篇博客系列篇.本篇为: v32.xx 鸿蒙内核源码分析(CPU篇) | 整个内核就是一个死循环 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度 ...
- spring源码分析-core.io包里面的类
前些日子看<深入理解javaweb开发>时,看到第一章java的io流,发觉自己对io流真的不是很熟悉.然后看了下JDK1.7中io包的一点点代码,又看了org.springframewo ...
- 鸿蒙内核源码分析(线程概念篇) | 是谁在不停的折腾CPU? | 百篇博客分析OpenHarmony源码 | v21.06
百篇博客系列篇.本篇为: v21.xx 鸿蒙内核源码分析(线程概念篇) | 是谁在不断的折腾CPU | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调 ...
- 鸿蒙内核源码分析(系统调用篇) | 开发者永远的口头禅 | 百篇博客分析OpenHarmony源码 | v37.03
百篇博客系列篇.本篇为: v37.xx 鸿蒙内核源码分析(系统调用篇) | 开发者永远的口头禅 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度谁 ...
- 鸿蒙内核源码分析(并发并行篇) | 听过无数遍的两个概念 | 百篇博客分析OpenHarmony源码 | v25.01
百篇博客系列篇.本篇为: v25.xx 鸿蒙内核源码分析(并发并行篇) | 听过无数遍的两个概念 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度 ...
- 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 百篇博客分析OpenHarmony源码 | v7.07
百篇博客系列篇.本篇为: v07.xx 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调 ...
- 鸿蒙内核源码分析(调度队列篇) | 内核有多少个调度队列 | 百篇博客分析OpenHarmony源码 | v6.05
百篇博客系列篇.本篇为: v06.xx 鸿蒙内核源码分析(调度队列篇) | 内核有多少个调度队列 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度 ...
- 鸿蒙内核源码分析(任务管理篇) | 任务池是如何管理的 | 百篇博客分析OpenHarmony源码 | v5.05
百篇博客系列篇.本篇为: v05.xx 鸿蒙内核源码分析(任务管理篇) | 任务池是如何管理的 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度谁 ...
- 鸿蒙内核源码分析(任务调度篇) | 任务是内核调度的单元 | 百篇博客分析OpenHarmony源码 | v4.05
百篇博客系列篇.本篇为: v04.xx 鸿蒙内核源码分析(任务调度篇) | 任务是内核调度的单元 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度 ...
随机推荐
- x名称空间中的内容
原文:x名称空间中的内容 x名称空间映射的是http://schemas.microsoft.com/winfx/2006/xaml,它包含的类均与XAML的解析有关,下面分三部分介绍 一:x名称空间 ...
- Django 下添加左侧字段显示和搜索
在对应的apps下建立xadmin.py from .models import EmailVerifyRecord import xadminclass EmailVerifyRecordAdmin ...
- Redis进阶实践之十八 使用管道模式提高Redis查询的速度
原文:Redis进阶实践之十八 使用管道模式提高Redis查询的速度 一.引言 学习redis 也有一段时间了,该接触的也差不多了.后来有一天,以为同事问我,如何向redis中 ...
- mqtt消息推送
https://github.com/wizinfantry/delphi-mqtt-clienthttps://github.com/Indemsys/Delphi_MQTT_mosquittoht ...
- RocketMQ配置
安装&配置 1.Clone&Build git clone -b develop https://github.com/apache/incubator-rocketmq.git cd ...
- QString之simplified()用于读取数据、规范数据,非常方便
在工程项目开发中,遇到这么个问题:手工计入文件中的数据,每行有三个,前两个是数字,最后一个是标识,现在把这3个数据提取出来. 一提取就出现问题了:由于手工导入,数据间使用空白间隔,有可能是一个空格,有 ...
- RPG Maker MV游戏解包
该文章最新版本请前往:https://www.crowsong.xyz/127.html 前言 使用Petschko's RPG-Maker-MV File-Decrypter进行解包 使用Petsc ...
- spring boot自定义配置文件
把一些可能会经常变动的东西写在配置文件中,可以增加程序的灵活性,避免多次改版发版. 在sping boot中除了自带的默认配置文件application.properties之外,我们还可以在reso ...
- 使用wireshark抓包分析-抓包实用技巧
目录 使用wireshark抓包分析-抓包实用技巧 前言 自定义捕获条件 输入配置 输出配置 命令行抓包 抓取多个接口 抓包分析 批量分析 合并包 结论 参考文献 使用wireshark抓包分析-抓包 ...
- 读书笔记——《谁说菜鸟不会数据分析—Python篇》
最近刚读完一本新书,关注的公众号作者出的“谁说菜鸟不会数据分析—Python篇”,话说现在很多微信公众号大牛都在出书,这貌似是一个趋势.. 说说这本书吧,我之前看过一些网文,对于数据分析这一块也有过一 ...