以 CH549 为例的 51 教程 | 图文 5. 通信:UART 和 SPI(上)

MCU Xy ⋅ 于 2021-08-19 15:39:44 ⋅ 303 阅读

:card_index: 点此回到教程主索引

目录

串口通信介绍

串口通信具体代码解析

USB 转 TTL 模块与串口调试助手的使用方法

实验现象

串口通信介绍

串口通信,通常称作UART,是一种串行、异步、全双工的通信协议。
1_串口

简单点说:串口通信有两根线,一条通信输出线,一条通信接受线,可以同时接受信息和输出信息。
2_rxtx

什么是波特率

波特率指的每秒钟传送的码元符号的个数,是度量信息传输速度的单位,使用者需要保证串口接受端和输出端的波特率一致。

串口通信具体代码解析

main.c

/**
  ******************************************************************
  * @file    main.c
  * @author  xy 
  * @version V1.0
  * @date    2021-3-31
  * @brief   串口通讯
  ******************************************************************
  * @attention
  * verimake 用于ch549例程
  * CH549 串口1~3 查询与中断收发演示,实现数据回环
  * 注意包含CH549_DEBUG.C
  ******************************************************************
  */
#include <CH549_sdcc.h>  //ch549的头文件,其中定义了单片机的一些特殊功能寄存器
#include <CH549_UART.h>   //CH549官方提供库的头文件,定义了一些关于pwm初始化,设置等函数
#include <CH549_DEBUG.h> //CH549官方提供库的头文件,定义了一些关于主频,延时,串口设置,看门口,赋值设置等基础函数
/********************************************************************
* TIPS:
*  引脚            功能
*  P2.6            默认UART1——RXD1
*  P2.7            默认UART1——TXD1
*  P1.6            UART1引脚映射————RXD1_
*  P1.7            UART1引脚映射————TXD1_
*  P0.4            UART2——RXD2
*  P0.5            UART2——TXD2
*  P0.6            UART3——RXD3
*  P0.7            UART3——TXD3
*********************************************************************/
void main( )
{
    UINT8 dat;
    CfgFsys( );                                                                //CH549时钟选择配置
    mDelaymS(20);
    CH549UART1Init();                                                          //串口1初始化
    CH549UART1Alter();                                                         
    //串口1引脚映射-将串口一映射到 p1.6 和 p1.7  P1.6(UART1引脚映射————RXD1_)(P1.7 UART1引脚映射————TXD1_)
    CH549UART2Init();                                                          //串口2初始化
    CH549UART3Init();                                                          //串口3初始化
    printf("hello world\n");                                                   //串口输出:“hello world”
    while(1);
}
/********************************************************************
* 函 数 名       : putchar
* 函数功能       : 将printf映射到串口通讯
* 输    入      : 字符串
* 输    出        : 字符串
********************************************************************/
int putchar( int a)
{      
   CH549UART1SendByte(a);                                                     //printf映射到串口1输出
   return(a);
}

与PWM代码一致,调用的是沁恒官方提供的库,因此main函数中的内容简洁,便于理解。

代码的重要部分

putchar函数

/********************************************************************
* 函 数 名       : putchar
* 函数功能       : 将printf映射到串口通讯
* 输    入      : 字符串
* 输    出        : 字符串
********************************************************************/
int putchar( int a)
{      
   CH549UART1SendByte(a);                                                     //printf映射到串口1输出
   return(a);
}

通过putchar函数将printf的输出方式改变为使用串口1来输出数据。

CH549_UART.c

、/********************************** (C) COPYRIGHT *******************************
* File Name          : 官方uart库
* Author             : WCH
* Version            : V1.0
* Date               : 2018/08/09
* Description        : CH549 串口初始化相关
*******************************************************************************/
#include <CH549_UART.h> 
#include <CH549_sdcc.h>  //ch549的头文件,其中定义了单片机的一些特殊功能寄存器
/*******************************************************************************
* Function Name  : CH549UART1Init
* Description    : UART1初始化函数,串口默认引脚 P26 P27
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void CH549UART1Init()
{
    SCON1 &= ~bU1SM0;                            //选择8位数据通讯
    SCON1 |= bU1SMOD;                            //快速模式
    SCON1 |= bU1REN;                             //使能接收
    SBAUD1 = 0 - FREQ_SYS/16/UART1_BUAD;         //波特率配置
    SIF1 = bU1TI;                                //清空发送完成标志
#ifdef UART1_INTERRUPT                           //开启中断使能
    IE_UART1 = 1;
    EA = 1;
#endif
}
/*******************************************************************************
* Function Name  : CH549UART1Alter()
* Description    : CH549串口1引脚映射,串口映射到 P16 P17
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void CH549UART1Alter()
{
    P1_MOD_OC |= (3<<6);                                                   //准双向模式
    P1_DIR_PU |= (3<<6);
    PIN_FUNC |= bUART1_PIN_X;                                              //开启引脚复用功能
}
/*******************************************************************************
* Function Name  : CH549UART1RcvByte()
* Description    : CH549UART1接收一个字节
* Input          : None
* Output         : None
* Return         : SBUF
*******************************************************************************/
UINT8  CH549UART1RcvByte( )
{
    while((SIF1&bU1RI) == 0)
    {
        ;    //查询接收
    }
    SIF1 = bU1RI;                                                          //清除接收中断
    return SBUF1;
}
/*******************************************************************************
* Function Name  : CH549UART1SendByte(UINT8 SendDat)
* Description    : CH549UART1发送一个字节
* Input          : UINT8 SendDat;要发送的数据
* Output         : None
* Return         : None
*******************************************************************************/
void CH549UART1SendByte(UINT8 SendDat)
{
    SBUF1 = SendDat;
    while((SIF1&bU1TI) == 0)
    {
        ;    //查询等待发送完成
    }
    SIF1 = bU1TI;                                                          //清除发送完成中断
}
#ifdef UART1_INTERRUPT
/*******************************************************************************
* Function Name  : UART1Interrupt(void)
* Description    : UART1 中断服务程序
*******************************************************************************/
void UART1Interrupt(void) __interrupt INT_NO_UART1 __using 1            //串口1中断服务程序,使用寄存器组1
{
    UINT8 dat;
    if(SIF1&bU1RI)
    {
        SIF1 = bU1RI;                                                     //清除接收完中断
        dat = SBUF1;
        CH549UART1SendByte(dat);
    }
}
#endif
/*******************************************************************************
* Function Name  : CH549UART2Init
* Description    : UART2初始化函数,串口默认引脚 P04 P05
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void CH549UART2Init()
{
    SCON2 &= ~bU2SM0;                            //选择8位数据通讯
    SCON2 |= bU2SMOD;                            //快速模式
    SCON2 |= bU2REN;                             //使能接收
    SBAUD2 = 0 - FREQ_SYS/16/UART2_BUAD;         //波特率配置
    SIF2 = bU2TI;                                //清空发送完成标志
#ifdef UART2_INTERRUPT                           //开启中断使能
    SCON2 |= bU2IE;                              //开启UART2中断,关闭ADC中断
    IE_UART2 = 1;
    EA = 1;
#endif
}
/*******************************************************************************
* Function Name  : CH549UART2RcvByte()
* Description    : CH549UART2接收一个字节
* Input          : None
* Output         : None
* Return         : SBUF
*******************************************************************************/
UINT8 CH549UART2RcvByte( )
{
    while((SIF2&bU2RI) == 0)
    {
        ;    //查询接收
    }
    SIF2 = bU2RI;                                                          //清除接收中断
    return SBUF2;
}
/*******************************************************************************
* Function Name  : CH549UART2SendByte(UINT8 SendDat)
* Description    : CH549UART2发送一个字节
* Input          : UINT8 SendDat;要发送的数据
* Output         : None
* Return         : None
*******************************************************************************/
void CH549UART2SendByte(UINT8 SendDat)
{
    SBUF2 = SendDat;
    while((SIF2&bU2TI) == 0)
    {
        ;    //查询等待发送完成
    }
    SIF2 = bU2TI;                                                          //清除发送完成中断
}
#ifdef UART2_INTERRUPT
/*******************************************************************************
* Function Name  : UART1Interrupt(void)
* Description    : UART1 中断服务程序
*******************************************************************************/
void UART2Interrupt( void ) __interrupt INT_NO_UART2  __using 1               //串口2中断服务程序,使用寄存器组1
{
    UINT8 dat;
    if(SIF2&bU2RI)
    {
        SIF2 = bU2RI;                                                     //清除接收完中断
        dat = SBUF2;
        CH549UART2SendByte(dat);
    }
}
#endif
/*******************************************************************************
* Function Name  : CH549UART3Init
* Description    : UART3初始化函数,串口默认引脚 P06 P07
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void CH549UART3Init()
{
    SCON3 &= ~bU3SM0;                            //选择8位数据通讯
    SCON3 |= bU3SMOD;                            //快速模式
    SCON3 |= bU3REN;                             //使能接收
    SBAUD3 = 0 - FREQ_SYS/16/UART3_BUAD;         //波特率配置
    SIF3 = bU3TI;                                //清空发送完成标志
#ifdef UART3_INTERRUPT                           //开启中断使能
    SCON3 |= bU3IE;                              //开启UART3中断,关闭PWM中断
    IE_UART3 = 1;
    EA = 1;
#endif
}
/*******************************************************************************
* Function Name  : CH549UART3RcvByte()
* Description    : CH549UART3接收一个字节
* Input          : None
* Output         : None
* Return         : SBUF
*******************************************************************************/
UINT8 CH549UART3RcvByte( )
{
    while((SIF3&bU3RI) == 0)
    {
        ;    //查询接收
    }
    SIF3 = bU3RI;                                                          //清除接收中断
    return SBUF3;
}
/*******************************************************************************
* Function Name  : CH549UART3SendByte(UINT8 SendDat)
* Description    : CH549UART3发送一个字节
* Input          : UINT8 SendDat;要发送的数据
* Output         : None
* Return         : None
*******************************************************************************/
void CH549UART3SendByte(UINT8 SendDat)
{
    SBUF3 = SendDat;
    while((SIF3&bU3TI) == 0)
    {
        ;    //查询等待发送完成
    }
    SIF3 = bU3TI;                                                          //清除发送完成中断
}
#ifdef UART3_INTERRUPT
/*******************************************************************************
* Function Name  : UART1Interrupt(void)
* Description    : UART1 中断服务程序
*******************************************************************************/
void UART3Interrupt( void ) __interrupt INT_NO_UART3 __using 1              //串口3中断服务程序,使用寄存器组1
{
    UINT8 dat;
    if(SIF3&bU3RI)
    {
        SIF3 = bU3RI;                                                     //清除接收完中断
        dat = SBUF3;
        CH549UART3SendByte(dat);
    }
}
#endif

官方库中定义了串口123的中断服务函数。
3_串口中断服务函数
只要有数据通过串口传入ch549就会立刻触发中断,接受数据。我们可以通过编写中断服务函数来达到我们所需要的目的,此处是将接受到的数据通过串口发送回去,达到数据回环的效果。

USB 转 TTL 模块与串口调试助手的使用方法

USB转TTL模块

套件中所提供的usb转ttl串口模块,他可以让你的计算机也拥有串口模块以此完成与单片机的串口通讯,使用此模块需要安装驱动,驱动为“安装包与所需文件”中的CH341SER.EXE,正常安装即可。
4_usb转ttl驱动
安装完成之后,模块插入电脑即可在设备管理器中的端口处发现模块。
5_设备管理器
PS:此处需要注意 ch549下载程序时必须断电,因此必须关闭 usb转ttl 串口模块才能打开下载模式.

串口调试助手

6_串口调试助手设置
第一步:将串口号设置为usb转ttl串口模块的串口号,在我的电脑上为com4。

第二步:将波特率与单片机设置的串口波特率保持一致,可以通过CH549_UART.h中查看设置的波特率。
7_bote
第三步:打开串口。

实验现象

1.按下单片机的RST键后在接收区看到"helloword"
8_现象1
符合代码
9_符合

2.在发送区随意发送数据,可以看到接收区也有发送的数据,完成数据回环。
10_现象2

回复数量: 0
    暂无评论~~
    • 请注意单词拼写,以及中英文排版,参考此页
    • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
    • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
    • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
    • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
    Ctrl+Enter