CC2541蓝牙学习——串口_0和1(寄存器版本)
CC2541有两个串行通信接口,分别是USART0和USART1,它们能够分别运行于异步UART模式或者同步SPI模式。两个USART具体同样的功能,可以设置在单独的I/O引脚。
来源-作者@欣庸:https://www.cnblogs.com/chenzhao207/p/4531941.html
1.UART模式
UART模式提供异步串行接口,在UART模式中,有2种接口选择方式:2线接口和4线接口。
- 2线接口,使用RXD、TXD。
- 4线接口,使用RXD、TXD、RTS和CTS。
I/O外设引脚映射如下图所示:
根据上面的外设I/O引脚映射可知:
UART0对应的外部设置IO引脚关系为:位置1:P0_2----RX P0_3----TX
重映射PERCFG |= BV(0) 位置2:P1_4----RX P1_5----TX
UART1对应的外部设置IO引脚关系为:位置1:P0_5----RX P0_4----TX
重映射PERCFG |= BV(1) 位置2:P1_7----RX P1_6----TX
UART模式的操作有以下特点。
- 8位或者9位负载数据
- 奇校验、偶校验或者无奇偶校验
- 配置起始位和停止位电平
- 配置LSB(最低有效位)或MSB(最高有效位)首先传输
- 独立接收中断
- 独立收发DMA触发
- 奇偶校验和帧检验出错状态
UART模式提供全双工传送,也就是说可以同时收发数据,传送一个UART字节包括1个起始位,8个数据位,1个作为可选的第9位数据或者奇偶校验位,再加上1个或者2个停止位。
UART操作由USART控制和状态寄存器UxCSR以及UART控制寄存器UxUCR来控制,x是USART的编号,数值为0或者1。
当UxCSR.MODE设置为1时设定为UART模式。
1)UART的发送过程
当USART收发数据缓冲器UxDBUF写入数据时,该字节自动发送到输出引脚TXD,UxDBUF寄存器时双缓冲的。当字节传送开始时,UxCSR.ACTIVE位变为高电平,而当字节传送结束时变为低电平。当传送结束时,UxCSR.TX_BYTE位设置为1。当USART收发数据缓冲寄存器就绪,准备接收新的发送数据时,就产生了一个中断请求,该中断在传送开始后立刻发生。
2)UART的接收过程
当1写入UxCSR.RE位时,UART开始接收数据。UART在输入引脚RXD上寻找有效起始位,并且设置UxCSR.ACTIVE位为1,当检测出有效起始位时,收到的字节就传入到接收寄存器,UxCSR.RX_BYTE位设置为1,该操作完成时,产生接收中断,同时UxCSR.ACTIVE变为0,通过寄存器UxDBUF提取收到的数据字节。当UxDBUF读出时,UxCSR.RX_BYTE位由硬件清零。
当运行UART模式时,内部的波特率发生器设置UART波特率。当运行在SPI模式时,内部的波特率发生器设置SPI主时钟频率。波特率由寄存器UxBAUD.BAUD_M[7:0] 和UxGCR.BAUD_E[4:0]定义。该波特率用于UART传送,也用于SPI传送的串行时钟速率。波特率定义公式:
式中:f是系统的时钟频率,等于16MHz或者32MHz
标准波特率所需的寄存器值如下表所示,该表适用于32MHz系统时钟。波特率误差,用百分数表示。
CC2530配置串口的一般步骤:
1、配置串口的备用位置,是备用位置1,还是备用位置2。配置寄存器PERCFG外设控制寄存器
2、配置端口的外设优先级。此处配置P0外设优先作为UART0。配置寄存器P2DIR
3、配置IO,使用外部设备功能。此处配置P0_2和P0_3用作串口UART0。配置寄存器P0SEL
4、配置相应串口的控制和状态寄存器。配置寄存器U0CSR、U0UCR
5、配置串口工作的波特率。配置寄存器U0GCR、U0BAUD
6、将对应的串口接收/发送中断标志位清0,清零:TCON.URX0IF、TCON.URX1IF、IRCON2.UTX0IF、IRCON2.UTX1IF
7、使能串口接收中断(一般发送不用中断),置1 IEN0.URX0IE
8、开总中断
中断相关的寄存器如下:
IEN0(0xA8)
TCON(0x88)
IRCON2(0xE8)
串口0配置如下:
/****************************************************************************
名 称: InitUart()
功 能: 串口初始化函数
入口参数: 无
出口参数: 无
****************************************************************************/
void InitUart(void)
{
#if UART0_P0PERCFG &= ~0x01; //USART0映射P2DIR &= ~0xc0; P0SEL |= BV(2) | BV(3);//配置P0.2和P0.3为外设,非GPIO
#else PERCFG |= BV(0); //USART0重映射P1SEL |= BV(4) | BV(5);//配置P1.4和P1.5为外设,非GPIO
#endifU0CSR |= BV(7); //配置当前为UART,非SPIU0GCR |= 11; //根据上述波特率设置表格设置115200波特率U0BAUD |= 216;// 根据上述波特率设置表格设置115200波特率UTX0IF = 0;//位寄存器,直接操作,清除中断标志U0CSR |= BV(6);//允许接收数据IEN0 |= BV(2);//打开接收中断EA=1;//打开总中断
}
总程序如下:
#include <ioCC2540.h>
//CC2541也可以使用该头文件
//串口收发验,波特率115200,8N1.typedef unsigned char uint8;
typedef char int8;
typedef unsigned short int uint16;#define LED1 P1_0 //定义P1.0口为LED1控制端
#define LED2 P1_1
/****************************************************************************
常用宏定义
****************************************************************************/
#define BV(x) (1<<(x))#define UART0_P0 1
#define UART1_P0 1//定义P0口为UART0、1输出端/****************************************************************************
名 称: DelayMS()
功 能: 毫秒延时,系统时钟不配置时默认使用内部16M,本demo中,时钟为外部32M
入口参数: msec 延时参数,注意,最大数值为65536ms
出口参数: 无
****************************************************************************/
void DelayMS(uint16 msec)
{ uint16 i,j;for (i=0; i<msec; i++)for (j=0; j<536*2; j++);
}/****************************************************************************
名 称: InitLed()
功 能: 设置LED相应的IO口
入口参数: 无
出口参数: 无
****************************************************************************/
void InitLed(void)
{P1DIR |= BV(0); // P1.0定义为输出LED1 = 0; // LED1灯熄灭 P1DIR |= BV(1); // P1.0定义为输出LED2 = 0; // LED1灯熄灭
}/****************************************************************************
名 称: InitUart()
功 能: 串口初始化函数
入口参数: 无
出口参数: 无
****************************************************************************/
void InitUart(void)
{
#if UART0_P0PERCFG &= ~0x01; //USART0映射P2DIR &= ~0xc0; P0SEL |= BV(2) | BV(3);//配置P0.2和P0.3为外设,非GPIO
#else PERCFG |= BV(0); //USART0重映射P1SEL |= BV(4) | BV(5);//配置P1.4和P1.5为外设,非GPIO
#endifU0CSR |= BV(7); //配置当前为UART,非SPIU0GCR |= 11; //根据上述波特率设置表格设置115200波特率U0BAUD |= 216;// 根据上述波特率设置表格设置115200波特率UTX0IF = 0;//位寄存器,直接操作,清除中断标志U0CSR |= BV(6);//允许接收数据IEN0 |= BV(2);//打开接收中断EA=1;//打开总中断}
/****************************************************************************
名 称: InitUart1()
功 能: 串口初始化函数
入口参数: 无
出口参数: 无
****************************************************************************/
void InitUart1(void)
{
#if UART1_P0PERCFG &= ~0x02; //USART1映射 P1SEL |= BV(4) | BV(5);//配置P0.4和P0.5为外设,非GPIO
#elsePERCFG |= BV(1); //USART1重映射//P2SEL|=BV(6);//P2SEL&=~BV(5);//P2DIR &=~BV(7);//P2DIR |=BV(6);P1SEL |= BV(6) | BV(7);//配置P1.6和P1.7为外设,非GPIO
#endifU1CSR |= BV(7); //配置当前为UART,非SPIU1GCR |= 11; //根据上述波特率设置表格设置115200波特率U1BAUD |= 216;// 根据上述波特率设置表格设置115200波特率UTX1IF = 0;//位寄存器,直接操作,清除中断标志U1CSR |= BV(6);//允许接收数据IEN0 |= BV(3);//打开接收中断EA=1;//打开总中断}
/****************************************************************************
名 称: UartSendString()
功 能: 串口发送函数
入口参数: Data:发送缓冲区 len:发送长度
出口参数: 无
****************************************************************************/
void UartSendString(int8 *Data, uint16 len)
{uint16 i;for(i=0; i<len; i++){U0DBUF = *Data++;while(UTX0IF == 0);UTX0IF = 0;}
}
/****************************************************************************
名 称: Uart1SendString()
功 能: 串口发送函数
入口参数: Data:发送缓冲区 len:发送长度
出口参数: 无
****************************************************************************/
void Uart1SendString(int8 *Data, uint16 len)
{uint16 i;for(i=0; i<len; i++){U1DBUF = *Data++;while(UTX1IF == 0);UTX1IF = 0;}
}
/****************************************************************************
名 称: UartSendByte()
功 能: 串口发送函数
入口参数: byte,带发送的数据
出口参数: 无
****************************************************************************/
void UartSendByte(int8 byte)
{U0DBUF = byte;while(UTX0IF == 0);UTX0IF = 0;
}
/****************************************************************************
名 称: Uart1SendByte()
功 能: 串口发送函数
入口参数: byte,带发送的数据
出口参数: 无
****************************************************************************/
void Uart1SendByte(int8 byte)
{U1DBUF = byte;while(UTX1IF == 0);UTX1IF = 0;
}
/****************************************************************************
名 称: UART1_ISR(void) 串口中断处理函数
描 述: 当串口 0 产生接收中断,将收到的数据保存在 RxBuf 中,每次接收一个字节
****************************************************************************/
#pragma vector = URX0_VECTOR
__interrupt void UART0_ISR(void)
{ URX0IF = 0; // 清中断标志Uart1SendByte(U0DBUF); //收到后uart1立即发送出去}
/****************************************************************************
Ãû ³Æ: UART1_ISR(void) ´®¿ÚÖжϴ¦Àíº¯Êý
Ãè Êö: µ±´®¿Ú 0 ²úÉú½ÓÊÕÖжϣ¬½«ÊÕµ½µÄÊý¾Ý±£´æÔÚ RxBuf ÖУ¬Ã¿´Î½ÓÊÕÒ»¸ö×Ö½Ú
****************************************************************************/
#pragma vector = URX1_VECTOR
__interrupt void UART1_ISR(void)
{ URX1IF = 0; // 清中断标志UartSendByte(U1DBUF); //收到后uart0立即发送出去}/*****************************************************************函 数 名:SysStartXOSC*功 能:系统时钟初始化*入口参数:无*出口参数:无*****************************************************************/void SysStartXOSC(void){SLEEPCMD &= ~0x04; // 启动所有晶振while (!(SLEEPSTA & 0x40)); // 等待晶振稳定 CLKCONCMD = (CLKCONCMD & 0x80) | 0x49; // 使用16M晶振作为主时钟while ((CLKCONSTA & ~0x80) != 0x49 ); // 等待主时钟切换到16M晶振CLKCONCMD = (CLKCONCMD & ~0x80) ; // 使用外部32K晶振作为休眠时钟while ( (CLKCONSTA & 0x80) != 0 ); // 等待睡眠时钟切换到外部32K晶振CLKCONCMD = (CLKCONCMD & 0x80) ; // 使用32M晶振作为主时钟while ( (CLKCONSTA & ~0x80) != 0 ); // 等待主时钟切换到32M晶振SLEEPCMD |= 0x04; // 关闭未使用的晶振}
void main(void)
{ //CLKCONCMD &= ~0x40; //设置系统时钟源为32MHZ晶振//while(CLKCONSTA & 0x40); //等待晶振稳定//CLKCONCMD &= ~0x47; //设置系统主时钟频率为32MHZ SysStartXOSC(); InitLed();InitUart(); //调置串口相关寄存器InitUart1();
#if UART0_P0 UartSendString("UART0\r\nP0.2--RX P0.3--TX\r\n",26); Uart1SendString("UART1\r\nP0.5--RX P0.4--TX\r\n",26);
#elseUartSendString("UART0\r\nP1.4--RX P1.5--TX\r\n",26); Uart1SendString("UART1\r\nP1.7--RX P1.6--TX\r\n",26);
#endifwhile(1){DelayMS(500);//UartSendByte(0x30);//Uart1SendByte(0x31);LED1=~LED1;LED2=~LED2;}
}
CC2541蓝牙学习——串口_0和1(寄存器版本)相关推荐
- 汇承4.0蓝牙BLE串口助手HC-COM的使用方法及出错的原因和改正方法
本文主要介绍在使用汇承4.0蓝牙BLE串口助手HC-COM,通过手机向蓝牙模块发送数据.或者通过手机向与蓝牙模块连接的单片机发送指令时,串口中断函数的编写方法及出错的原因和改正方法 我们怎 ...
- 【转载】传统蓝牙协议栈 串口协议SPP
零. 概述 主要介绍下蓝牙协议栈(bluetooth stack) 串口协议(bluetooth SPP)Serial Port Profile 协议概念介绍. 一. 声明 本专栏文章我们会以连载的方 ...
- 嵌入式学习——串口通信小试
嵌入式学习--串口通信小试 目录 嵌入式学习--串口通信小试 1.了解串口协议和RS-232.485标准,以及RS-232.485电平与TTL电平的区别 1.1 什么是串口协议 1.2 RS-232标 ...
- Android BLE(2)---蓝牙学习
Android 普通蓝牙学习 需要的权限 <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" ...
- PC下串口IO空间及其寄存器详解
2019独角兽企业重金招聘Python工程师标准>>> 串口(Serial UART), 全称是通用异步收发口universal asynchronous receiver/tran ...
- QT学习串口编程之串口软件的UI设计
学会了如何使用QT进行界面设计之后,接下来让我们来进入第二阶段的学习--串口编程吧. 首先我们需要对串口软件的UI界面进行仿写. 首先存在一个接收方和发送方,接收框主要是串口软件接收设备发来的数据,发 ...
- cc2541中文数据手册及cc2541蓝牙源程序
cc2541中文数据手册及cc2541蓝牙源程序 发表于 2018-05-02 17:09:35 无线通信15人已加入 +加入圈子 cc2541概述 CC2541 是一款针对低能耗以及私有 2.4GH ...
- crh寄存器_牛人的STM32学习笔记(寄存器版本).doc
牛人的STM32学习笔记(寄存器版本) 一.GPIO口的配置 STM32的DGPIO口最多可以有7组(GPIOa~GPIOg),而每一组GPIO口均有16个双向IO组成.并且没个IO口均可配置成8种模 ...
- 蓝牙学习五(广播包分析wireshark)
1.简介 软件工具:wireshark 硬件抓包工具:nrf52840 dongle 2.数据包分析 使用wireshark抓到的数据包分为两个部分,一部分是软件自己添加的内容,另一部分才是广播出来的 ...
- 无人机蓝牙图传串口助手APP(地面端、飞机端)
这个APP是在2016年11月底-12月初开发的,现在想把这项目开源共享给有需要的开发者参考!源码有需要请留言联系本人,由于本项目属于公司项目,不能完全开源出来,只提供部分技术支持!请谅解! 由于地面 ...
最新文章
- python官网下载安装教程-Python和Anoconda和Pycharm安装教程
- 前端基础:web语义化
- C语言宏定义中使用 do{}while(0) 的情形
- 常用的相似性度量(距离总结)
- 如何理解java反射_怎么理解java反射
- 【转载】同步和互斥的POSIX支持(互斥锁,条件变量,自旋锁)
- CodeForces - 336D Vasily the Bear and Beautiful Strings(dp+组合数学)
- SpringMVC框架第一天
- 刚刚看到 PNaCl, 这才是我一直期待的跨平台的好东西!
- NOIP2015题解
- 陀螺信号一阶差分matlab,卡尔曼滤波在陀螺漂移时间序列模型中的应用
- sublime text3找到定义_决策易aPaaS,一款非技术人员也能使用的自定义开发神器
- frontpage 2010.2003绿色版
- openwrt 开启KV漫游
- 基于似然比检验统计量的异常轨迹检测
- 没有对象,你凭什么成为百万富翁
- JS逆向 2021-8-16 网易云音乐 params、encSecKey参数
- 图片上传实时预览效果
- 「 C++ 函数 」“WSAStartup()使用”讲解
- 微信公众号发送模版消息详细过程
热门文章
- 什么是像素格式(色彩采样、色度抽样)RGB 4:4:4、(Limit)RGB 4:4:4、Ycbcr 4:4:4、Ycbcr 4:2:2、Ycbcr 4:2:0又是什么?
- 鸿蒙大陆9.1正式版礼包,鸿蒙大陆2.0正式版
- 16比9尺寸是多少厘米_16比9尺寸的长宽是多少像素
- Mangos某人经验
- linux根据uid反查用户名
- 使用 关键字来创建python自定义函数_python 自定义函数
- vue倒计时翻页插件
- 个性化不和谐帐户的8种方法
- C++中begin()函数的含参数的使用
- Android开发:引入重复包报错Error:Execution failed for task ':app:transformDexArchiveWithExternalLibsDe...’解决方法