zigbee CC2530 系列教程 7 串口数据收发实验

4.6串口数据收发实验

4.6.1 实验目的

1.了解串口通信的相关知识;

2.学习CC2530单片机串口相关寄存器配置,实现串口通信功能;

4.6.2 实验讲解

CC2530芯片有两个串行接口UART0和UART1:

UART0对应RXD(P02)、TXD(P03);

UART1对应RXD(P04)、TXD(P05);

在开发板中只接出了串口0(UART0),从串口原理图就可以看出,CC2530的串口信号与P02、P03复用,由于USB接口的众多优势,越来越普遍的被应用到计算机以及工业现场,而RS232接口的市场地位也逐渐淡漠,如图4-6所示,我们的开发板将RS232 信号通过PL2303转换为USB信号与电脑或者工业设备进行串口通信。

图4-6 开发板串口TTL与USB转换电路原理图

要实现CC2530的串口通信除了掌握硬件电路原理,还有一个关键的环节就是有关串口通信寄存器软件配置U0CSR、U0GCR、U0BAUD、U0DBUF、UTX0IF,串口相关寄存器功能描述如表4-4所示:

表4-4相关寄存器功能描述

U0CSR(UART0 控

制和状态寄存器)

Bit7:MODE

0:SPI 模式

1:UART 模式

Bit6:RE

0:接收器禁止

1:接收器使能

Bit5:SLAVE

0:SPI 主模式

1:SPI 从模式

Bit4:FE

0:没有检测出帧错误

1:收到字节停止位电平出错

Bit3:ERR

0:没有检测出奇偶检验出错

1:收到字节奇偶检验出错

Bit2:RX_BYTE

0:没有收到字节

1:收到字节就绪

Bit1:TX_BYTE

0:没有发送字节

1:写到数据缓冲区寄存器的最后字节已

经发送

Bit0:ACTIVE

0:USART空闲

1:USART忙

U0GCR(UART0 通

用控制寄存器)

Bit7:CPOL

0:SPI 负时钟极性

1:SPI 正时钟极性

Bit6:CPHA

0:当来自 CPOL 的 SCK 反相之后又返回CPOL 时,数据输出到 MOSI;当来自 CPOL的 SCK 返回 CPOL 反相时,输入数据采样到MISO

1:当来自 CPOL 的 SCK 返回 CPOL 反相时,数据输出到 M OSI ;当来自 CPOL 的 SCK 反相之后又返回 CPOL 时,输入数据采样到 MISO

Bit5:ORDER

0:LSB 先传送

1:MSB 先传送

Bit[4:0]:BAUD_E

波特率指数值 BAUD_E 连同 BAUD_M

一起决定了 UART 的波特率

U0BAUD(UART0 波特率控制寄存器)

Bit[7:0]:BAUD_M

波特率尾数值 BAUD_M 连同 BAUD_E

一起决定了 UART 的波特率

U0DBUF ( UART0

收发数据缓冲区)

串口发送/接收数据缓冲区

UTX0IF(发送中断

标志)

中断标志5 IRCON2 的Bit1

0:中断未挂起

1:中断挂起

在本实验中我们采用USART0接口,具体的软件操作以及串口寄存器配置步骤如下:

1、硬件接口配置,配置P02和P03用作串口 UART0。

2、配置相应串口的控制和状态寄存器。

3、配置串口工作的波特率。CC2530单片机的串口数据传输的波特率决定于通用控制寄存器U0GCR的Bit[4:0]——BAUD_E和波特率控制寄存器U0BAUD——BAUD_M,具体的计算公式如式4-1

波特率

在32MHz的系统时钟下常用的波特率所对应的BAUD_M和BAUD_E的值如下表4-5。

表4-5在32MHz的系统时钟下常用的波特率所对应的BAUD_M和BAUD_E的值

常用的波特率

BAUD_M

BAUD_E

误差

2400

59

6

0.14

4800

59

7

0.14

9600

59

8

0.14

14400

216

9

0.03

19200

59

10

0.14

28800

216

11

0.03

38400

59

12

0.14

57600

216

13

0.03

76800

59

14

0.14

115200

216

15

0.03

230400

216

16

0.03

串口寄存器配置程序如下

CLKCONCMD &= ~0x40;      //设置系统时钟源为 32MHZ 晶振

while(CLKCONSTA & 0x40);   //等待晶振稳定

CLKCONCMD &= ~0x47;     //设置系统主时钟频率为 32MHZ

PERCFG = 0x00;             //位置 1 P0 口

P0SEL = 0x3c;               //P0_2,P0_3,P0_4,P0_5 用作串口,第二功能

P2DIR &= ~0XC0;            //P0 优先作为 UART0 ,优先级

U0CSR |= 0x80;              //UART 方式

U0GCR |= 11;                //U0GCR 与 U0BAUD 配合

U0BAUD |= 216;             // 波特率设为 9600

UTX0IF = 0;                 //UART0 TX 中断标志初始置位 1 (收发时候)

U0CSR |= 0X40;              //允许接收

IEN0 |= 0x84;                // 开总中断,接收中断

具体程序如下:

#include <ioCC2530.h>

#include <string.h>

#define uint unsigned int

#define uchar unsigned char

//定义控制LED灯的端口

#define LED1 P1_0    //定义LED1为P10口控制

#define LED2 P1_1    //定义LED1为P11口控制

//函数声明

void Delayms(uint xms);    //延时函数

void InitLed(void);        //初始化P1口

void InitUart();           //初始化串口

void Uart_Send_String(char *Data,int len);

char Rxdata[50];

uchar RXTXflag = 1;

char temp;

uchar  datanumber = 0;

/****************************

          延时函数

*****************************/

void Delayms(uint xms)   

{

  uint i,j;

  for(i=xms;i>0;i--)

    for(j=587;j>0;j--);

}  

/****************************

//初始化程序

*****************************/

void InitLed(void)

{

  P1DIR |= 0x03; //P10、P11定义为输出

  LED1 = 0;     

  LED2 = 0;    

}

/****************************************************************

   串口初始化函数     

***********************************************************/

void InitUart()

{

    CLKCONCMD &= ~0x40;      // 设置系统时钟源为 32MHZ晶振

    while(CLKCONSTA & 0x40);    // 等待晶振稳定

    CLKCONCMD &= ~0x47;      // 设置系统主时钟频率为 32MHZ

    

    PERCFG = 0x00;           //位置1 P0口

    P0SEL  = 0x3c;           //P0_2,P0_3,P0_4,P0_5用作串口,第二功能

    P2DIR &= ~0XC0;         //P0优先作为UART0 ,优先级

    

    U0CSR |= 0x80;           //UART 方式

    U0GCR |= 8;              //U0GCR与U0BAUD配合     

    U0BAUD |= 59;           //波特率设为9600

    UTX0IF = 0;              //UART0 TX 中断标志初始置位1  (收发时候)

    U0CSR |= 0X40;           //允许接收

    IEN0 |= 0x84;             //开总中断,接收中断    

}

/****************************************************************

串口发送字符串函数    

****************************************************************/

void Uart_Send_String(char *Data,int len)

{

    int j;

    for(j=0;j<len;j++)

    {

        U0DBUF = *Data++;

        while(UTX0IF == 0);      //发送完成标志位

        UTX0IF = 0;

    }

}

/***************************

//主函数

***************************/

void main(void)

{

    InitLed(); //调用初始化函数

    InitUart();

    while(1)

    {

        if(RXTXflag == 1) //接收状态

        {

            LED1=1;    //接收状态指示

            if( temp != 0)

            {

                //'#'被定义为结束字符,最多能接收50个字符

                if((temp!='#')&&(datanumber<50))

                {

                    Rxdata[datanumber++] = temp;

                }

                else

                {

                    RXTXflag = 3; //进入发送状态

                    LED1=0;     //关指示灯

                }

                temp  = 0;

            }

        }

        if(RXTXflag == 3)     //发送状态

        {

            LED2= 1;                           

            U0CSR &= ~0x40;   //禁止接收

            Uart_Send_String(Rxdata,datanumber); //发送已记录的字符串。

            U0CSR |= 0x40;    //允许接收

            RXTXflag = 1;     //恢复到接收状态

            datanumber = 0;    //指针归0

            LED2 = 0;         //关发送指示

        }    

    }

}

/****************************************************************

串口接收一个字符: 一旦有数据从串口传至CC2530, 则进入中断,

将接收到的数据赋值给全局变量temp.

****************************************************************/

#pragma vector = URX0_VECTOR

__interrupt void UART0_ISR(void)

{

    URX0IF = 0;    //清中断标志

    temp = U0DBUF;                           

}

4.6.3 实验效果

     实验时,下载程序到开发板后,插上USB线,然后将S1开关拨到ON,即可进行串口实验,实验效果如图4-7所示

图4-7 实验效果图

扩展知识——串口通信基础

在串行通信中,数据在1位宽的单条线路上进行传输,一个字节的数据要分为8次,由低位到高位按顺序一位一位的进行传送。

  串行通信的数据是逐位传输的,发送方发送的每一位都具有固定的时间间隔,这就要求接收方也要按照发送方同样的时间间隔来接收每一位。不仅如此,接收方还必须能够确定一个信息组的开始和结束。

  常用的两种基本串行通信方式包括同步通信和异步通信。

异步通信规定传输的数据格式由起始位(start bit)、数据位(data bit)、奇偶校验位(parity bit)和停止位(stop bit)组成,如图4-8所示(该图中未画出奇偶校验位,因为奇偶检验位不是必须有的,如果有奇偶检验位,则奇偶检验位应该在数据位之后,停止位之前)。

图4-8 异步通信数据格式

  (1)起始位:起始位必须是持续一个比特时间的逻辑0电平,标志传输一个字符的开始,接收方可用起始位使自己的接收时钟与发送方的数据同步。

  (2)数据位:数据位紧跟在起始位之后,是通信中的真正有效信息。数据位的位数可以由通信双方共同约定,一般可以是5位、7位或8位,标准的ASCII码是0~127(7位),扩展的ASCII码是0~255(8位)。传输数据时先传送字符的低位,后传送字符的高位。

  (3)奇偶校验位:奇偶校验位仅占一位,用于进行奇校验或偶校验,奇偶检验位不是必须有的。如果是奇校验,需要保证传输的数据总共有奇数个逻辑高位;如果是偶校验,需要保证传输的数据总共有偶数个逻辑高位。

  举例来说,假设传输的数据位为01001100,如果是奇校验,则奇校验位为0(要确保总共有奇数个1),如果是偶校验,则偶校验位为1(要确保总共有偶数个1)。

  由此可见,奇偶校验位仅是对数据进行简单的置逻辑高位或逻辑低位,不会对数据进行实质的判断,这样做的好处是接收设备能够知道一个位的状态,有可能判断是否有噪声干扰了通信以及传输的数据是否同步。

  (4)停止位:停止位可以是是1位、1.5位或2位,可以由软件设定。它一定是逻辑1电平,标志着传输一个字符的结束。

(5)空闲位:空闲位是指从一个字符的停止位结束到下一个字符的起始位开始,表示线路处于空闲状态,必须由高电平来填充。

发布了128 篇原创文章 · 获赞 51 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/aa120515692/article/details/104007026
今日推荐