04_CC2530+Uart串口通信

04_CC2530+UART串口通信

串口通信基本概念

  • 串行通信: 数据字节一位位地依次传送的通信方式, 串行通信的速度慢, 但用的传输线条数少, 成本低适用于远距离的数据传送
  • 并行通信: 数据字节的各位同事传送的通信方式, 优点是数据传送速度快, 缺点是占用的传输线条数多, 适用于近距离通信, 远距离通信的成本较高
  • 异步通信: 一次通信传送一个字符帧, 发送的字符之间的时间间隔可以是任意的, 优点是通信设备简单、价格低廉, 但因为具有起始位和停止位, 传输效率较低

  • 同步通信: 进行通信前先建立同步, 发送频率和接受方的接受频率要同步。在发送信息时, 将多个字符加上同步字符组成一个信息帧, 有一个统一的时钟控制发送端的发送, 接收端识别到同步字符后, 就认为开始一个信息帧, 此后位数作为实际传输信息处理。优点: 传输速度较快, 可用于点对多点 缺点: 需要使用专用的时钟控制线实现同步, 对于长距离通信成本较高, 通信速率也会降低。一般用于同一PCB上芯片级之间的通信

USART和UART的区别

  • UART(universal asynchronous receiver and transmitter) 通用异步收/发器

  • USART(universal synchronous asynchronous receiver and transmitter) 通用同步/异步收/发器

  • USARTUART增强型

  • CC2530芯片有USART0USART1串行通信接口, 它们能够分别运行于异步UART模式或者同步SPI 模式,两个USART具有同样的功能

UART串口参数及时序(串行异步通讯)

  • 波特率: 串口通信的速率,通讯双方的波特率需要一致
  • 起始位: 标志一个数据帧的开始, 固定为低电平
  • 数据位: 数据帧的有效载荷, 1为高电平, 0为低电平, 低位先行
  • 校验位: 用于数据验证, 根据数据位计算得来
  • 停止位: 用于数据帧间隔, 固定为高电平

硬件电路与CH340 USB转串口芯片

  • 简单双向串口通信有两根通信线(发送端TX和接受端RX)
  • TX与RX需要交叉连接
  • 当只需单向的数据传输时, 可以只接一根通信线
  • 当电平标准不一致时, 需要加电平转换芯片
  • 由于单片机UART外设电脑USB接口采用的电平标准不同,通常需要通过CH340芯片进行电平转换,且电脑上需要安装相应的CH340驱动程序

在这里插入图片描述

  • Note: 若开发板上有电平转换芯片,一般只需用数据线直接将电脑开发板上USB接口连接。若开发板上没有电平转换芯片,则需找到对应串口的引脚, 通过外置的USB转TTL模块与电脑相连接

CC2530 UART通信

CC2530USART0USART1两个串行通信接口,它们能够分别运行于异步UART模式或者同步SPI 模式。两个USART具有同样的功能,可以设置在单独的 I/O 引脚。

UART模式

UART模式提供异步串行接口。在UART模式中,接口使用2线或者含有引脚RXDTXD可选RTSCTS的4线。UART模式具有以下特点:

  • 8位或者9位负载数据
  • 奇校验、偶校验或者无奇偶校验
  • 配置起始位和停止位电平(默认起始位低电平,停止位高电平)
  • 配置LSB或者MSB首先传送
  • 独立收发中断
  • 独立收发DMA触发
  • 奇偶校验和帧校验出错状态
UART发送
  • 当往UxBUF(USART 收/发数据缓冲器寄存器) 写入数据时,该字节发送到输出引脚 TXDx
  • 当字节传送开始时,UxCSR.ACTIVE位变为高电平,而当字节传送结束时为低。当传送结束时, UxCSR.TX_BYTE位设置为 1
UART接收
  • 当1写入 UxCSR.RE 位时,在UART上数据接收就开始了。(开启接收,需要配置完UART所有参数后)
  • UART会在输入引脚RXDx中寻找有效起始位,当检测出有效起始位时,收到的字节就传入到接收寄存器,并将UxCSR.RX_BYTE位设置为 1,接收完一个字节后会产生一个中断
  • 通过寄存器UxBUF提供收到的数据字节。当UxBUF读出时,UxCSR.RX_BYTE位由硬件清 0
USART中断

​ 每个USART都有两个中断:URXx(接收完成中断)UTXx(发送完成中断)USART0相关中断使能和中断标志如下:

  • USART0 RX:IEN0.URX0IE
  • USART0 TX:IEN2.UTX0IE
  • USART0 RX:TCON.URX0IF
  • USART0 TX:IRCON2.UTX0IF
波特率的产生

​ 由寄存器 **UxBAUD.BAUD_M[7:0]**和 UxGCR.BAUD_E[4:0]定义波特率。公式如下:
波特率 = ( 256 + B A U D _ M ) ∗ 2 B A U D _ E 2 28 ∗ F \begin{aligned} 波特率=\frac{(256+BAUD\_M)*2^{BAUD\_E}}{2^{28}}*F\\ \end{aligned} 波特率=228(256+BAUD_M)2BAUD_EF
​ 其中: F
系统时钟频率

UART通信相关寄存器
端口配置相关寄存器

​ 由于CC2530USART0有两个可选位置(如下图所示),因此需要配置相关寄存器,来选择USART0所用的引脚。

在这里插入图片描述

​ 需要配置的寄存器有:

  • PERCFG:外设I/O控制寄存器
  • P2DIR:端口2方向和端口0外设优先级控制
  • P0SEL:端口0功能选择
UART串口参数配置相关寄存器

​ 在使用UART通讯前,要将USART配置成UART模式,并设置通讯时的串口参数(见UART串口参数及时序小节)。需要配置的寄存器有:

  • U0CSRUSART0控制和状态寄存器
  • U0UCRUSART0 UART控制寄存器
  • U0BAUDUSART0波特率控制
  • U0GCRUSART0通用控制
USART中断配置相关寄存器

​ 一般只用到接收中断,用于接收信息。无特殊情况,不需要用到发送中断。与USART0接收中断相关寄存器有:

  • URX0IFUSART0接收中断标志

  • URX0IEUSART0接收中断使能

  • IEN0.EA: 全局中断使能

    配置完上述寄存器后,还需重写putchar函数,即可用printf函数将信息从串口中发送出去。在接收中断服务函数中,完成信息的接受,并做出相应的回答。

具体代码讲解

项目结构

Serial.c用于实现UART通信SystemTimer中的源文件,主要用于实现Delay_ms函数,下面将重点讲解serial.c中的代码。Delay_ms函数相关代码在基础篇03中有详细介绍,不在赘述。
在这里插入图片描述

Serial.c
#include <ioCC2530.h>
#include "serial.h"
#include <stdio.h>

unsigned char RxBuf;   // 接收缓存
unsigned char RxData[RXLEN];  // 数据保存
unsigned char RxState = 0;  // 接收状态  0 等待包头'@'   1 接收数据
/**
* @brief 初始化串口 UART0
*/
void Serial_Init(void)
{
  	// 端口配置
	PERCFG = 0x00;  // 选用UART0默认位置 P0_2 Rx  P0_3 Tx
	P2DIR &= 0x3f;  // 选用UART0作为第一优先级指派给端口0
	P0SEL |= 0x0C;  // P0端口 2、3引脚设置为外设功能
	// UART 配置
	U0CSR |= 0x80;  // 选择UART模式
	U0UCR |= 0x02;  // 8bit 无校验 1bit停止位
	// 波特率设置 Baud = (256 + BAUD_M)*2^(BAUD_E) / 2^28 * F    F为系统时钟频率 32MHz
	// 若波特率要设置成9600 则BAUD_M = 44   BAUD_E = 8
	U0BAUD |= 0x2C;  // 44
	U0GCR |= 0x08;  // 8
	
	// 配置接收中断
	URX0IF = 0;   // 清除接收中断标志
	URX0IE = 1;   // 使能接受中断
	EA = 1;   // 开启全局中断
	U0CSR |= 0x40;  // 接收器使能 需要先配置完USART所有参数
}

/**
* @brief 重写 putchar函数 UART0 printf函数底层调用的就是该函数 重写过后,调用printf会通过串口发送信息
*/
__ATTRIBUTES int putchar(int c)
{
    UTX0IF = 0;   // 清除发送标志位
    U0DBUF = (char)c;
    while(UTX0IF == 0);  // 等待发送成功  发送成功时 发送标志位复位
    return(c);
}

/**
* @brief UART0 接收中断服务函数
*/
#pragma vector = URX0_VECTOR
__interrupt void USAT0_ISR(void)
{
  	static unsigned int idx = 0;  // 接收数组下标 static关键字只初始化一次
  	if(U0CSR&0x04 != 0)   // 接收到数据
	{
		RxBuf = U0DBUF;   // 从UART寄存器中读取数据
		if(RxState == 0)   // 等待包头
		{
		  if(RxBuf == '@')
		  {
		  	RxState = 1;  // 切换状态为接收信息
			idx = 0;  // 重置下标
		  }
		}
		else if(RxState == 1) // 读取数据
		{
		  if(idx < RXLEN && (RxBuf != '\n'))  // 接收数据
		  {
		  	RxData[idx++] = RxBuf;  //从接收缓存区中读取信息,放到接收数组中
		  }
		  else    // 数据超过限制 或者 收到包尾
		  {
		  	idx = 0;  // 重置下标
			RxState = 0;  // 切换状态为等待包头
			printf("Get Info:%s\n", RxData);  // 回复消息
		  }  
		}
	}
	URX0IF = 0;  // 清除中断标志
}
  • UART0接收中断服务函数:实现接收包头为'@'的消息,并在接收到包尾\n时,发送接收数组RxData中的数据作为回复。
  • 具体实现看代码,非常详细
Serial.h
#ifndef __SERIAL_H
#define __SERIAL_H
#define RXLEN 256   // 接收数据最大长度
void Serial_Init(void);
#endif
main.c
#include <ioCC2530.h>
#include "delay.h"
#include <stdio.h>
#include "serial.h"

void main(void)
{
 	Delay_Init();  // 初始化延时函数, 基于定时器3实现
	Serial_Init(); // 初始化串口
	while(1)
	{
		printf("%s\n", "hello zigbee!\n");  // 每过五秒向上位机发送消息
		Delay_ms(5000);
	}
}
  • NoteDelay_ms()相关代码见基础篇03

实验现象

发送消息

​ 大约每隔5s上位机收到从单片机串口发来的消息
在这里插入图片描述

接收消息

​ 根据回复内容,可以判断单片机正确接受到上位机的消息

在这里插入图片描述

参考资料

STM32入门笔记10_USART串口通信+案例:上位机控制LED亮灭(USART串口通信、TIM定时器、EXTI综合案例)-优快云博客

CC2530中文数据手册完全版

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值