打印
[产品介绍及宣传专区]

CW32的UART单线半双工模式

[复制链接]
758|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
芯源新闻官|  楼主 | 2023-5-11 16:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一、简介
半双工即Half duplex Communication,是指在通信过程的任意时刻,信息既可由A传到B,又能由B传A,但同时只有一个方向上的传输存在。由于这种方式要频繁变换信道方向,故效率低,但可以节约传输线路。半双工方式适用于终端与终端之间的会话式通信。

二、实际操作(以CW32L083为例)
设置 UARTx_CR2.SIGNAL 为 1 使 UART 工作于单线半双工工作模式。在该模式下,使用 UARTx_TXD 引脚进行数据的发送和接收,不占用 UARTx_RXD 引脚(UARTx_RXD 可作通用 IO 使用)。写数据到 UARTx_TDR 寄存器后,UARTx_TXD 引脚立即进入发送状态,输出 UARTx_TDR 寄存器中的数据。数据 发送完成后,UARTx_TXD 引脚恢复到常态的接收状态。没有发送数据时,UARTx_TXD 引脚处于接收状态,数据接收完成后,接收完成标志位 UARTx_ISR.RC 会被硬件置 位,此时应尽快读取 UARTx_RDR 寄存器,并清除 UARTx_ISR.RC 标志位。

UART工作在单线半双工模式时,UARTx_TXD引脚需要配置为开漏输出。另外用户应采取适当的应用层保护机制,以确保不会出现多主机同时向总线发送数据。

三、UART单线半双工通信示例
硬件采用CW32L083VxTx StartKit单板,用杜邦线连接PA08和PA06引脚。
UARTy查询方式发送TxBuffer1缓冲区中的数据,UARTz查询方式接收数据,并存储到RxBuffer2缓冲区。
UARTz查询方式发送TxBuffer2缓冲区中的数据,UARTy查询方式接收数据,并存储到RxBuffer1缓冲区。
比较TxBuffer1和RxBuffer2、TxBuffer2和RxBuffer1,如果数据一致,则LED1亮,否则LED2亮。
1.配置RCC
void RCC_Configuration(void)
{
    RCC_HSI_Enable(RCC_HSIOSC_DIV6); //SYSCLK = HSI = 8MHz = HCLK = PCLK
    RCC_AHBPeriphClk_Enable(UARTy_GPIO_CLK | UARTz_GPIO_CLK | RCC_AHB_PERIPH_GPIOC, ENABLE); //外设时钟使能
    UARTy_APBClkENx(UARTy_CLK, ENABLE);
    UARTz_APBClkENx(UARTz_CLK, ENABLE);
}
2.配置GPIO
void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    UARTy_AFTX; //UART TX 复用
    UARTz_AFTX;
    UARTy_TXPUR; //UART TX PUR
    UARTz_TXPUR;
    GPIO_InitStructure.Pins = UARTy_TxPin;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; //开漏输出
    GPIO_Init(UARTy_GPIO, &GPIO_InitStructure);
    GPIO_InitStructure.Pins = UARTz_TxPin;
    GPIO_Init(UARTz_GPIO, &GPIO_InitStructure);
   
    GPIO_InitStructure.Pins = GPIO_PIN_3 | GPIO_PIN_2; //PC3 LED1 / PC2 LED2
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_Init(CW_GPIOC, &GPIO_InitStructure);
    PC03_SETLOW();//LED灭
    PC02_SETLOW();
}
3.配置UART
void UART_Configuration(void)
{
    UART_InitTypeDef UART_InitStructure = {0};

    UART_InitStructure.UART_BaudRate = UARTyz_BaudRate; // 波特率
    UART_InitStructure.UART_Over = UART_Over_16; // 采样方式
    UART_InitStructure.UART_Source = UART_Source_PCLK; // 传输时钟源UCLK
    UART_InitStructure.UART_UclkFreq = UARTyz_UclkFreq; // 传输时钟UCLK频率
    UART_InitStructure.UART_StartBit = UART_StartBit_FE; // 起始位判定方式
    UART_InitStructure.UART_StopBits = UART_StopBits_1; // 停止位长度
    UART_InitStructure.UART_Parity = UART_Parity_No ; // 校验方式
    UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
    UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx; // 发送/接收使能
    UART_Init(UARTy, &UART_InitStructure);
    UART_Init(UARTz, &UART_InitStructure);
}
4.定义变量
//UARTy
#define  UARTy                         CW_UART1
#define  UARTy_CLK                     RCC_APB2_PERIPH_UART1
#define  UARTy_APBClkENx               RCC_APBPeriphClk_Enable2
#define  UARTy_GPIO_CLK                RCC_AHB_PERIPH_GPIOA
#define  UARTy_GPIO                    CW_GPIOA
#define  UARTy_TxPin                    GPIO_PIN_8
#define  UARTy_AFTX                    PA08_AFx_UART1TXD()
#define  UARTy_TXPUR                   PA08_PUR_ENABLE();

//UARTz
#define  UARTz                         CW_UART2
#define  UARTz_CLK                     RCC_APB1_PERIPH_UART2
#define  UARTz_APBClkENx               RCC_APBPeriphClk_Enable1
#define  UARTz_GPIO_CLK                RCC_AHB_PERIPH_GPIOA
#define  UARTz_GPIO                    CW_GPIOA
#define  UARTz_TxPin                    GPIO_PIN_6
#define  UARTz_AFTX                    PA06_AFx_UART2TXD()
#define  UARTz_TXPUR                   PA06_PUR_ENABLE()
#define  UARTyz_BaudRate               9600
#define  UARTyz_UclkFreq                8000000
#define  TxBufferSize1                   (ARRAY_SZ(TxBuffer1) - 1)
#define  TxBufferSize2                   (ARRAY_SZ(TxBuffer2) - 1)
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);
uint8_t TxBuffer1[] = "\r\nCW32L083 UART HalfDuplex: UARTy -> UARTz\r\n";
uint8_t TxBuffer2[] = "\r\nCW32L083 UART HalfDuplex: UARTz -> UARTy\r\n";
uint8_t RxBuffer1[TxBufferSize2];
uint8_t RxBuffer2[TxBufferSize1];
uint32_t NbrOfDataToRead1 = TxBufferSize2;
uint32_t NbrOfDataToRead2 = TxBufferSize1;
uint8_t TxCounter1 = 0, RxCounter1 = 0;
uint8_t TxCounter2 = 0, RxCounter2 = 0;
volatile TestStatus TransferStatus1 = FAILED, TransferStatus2 = FAILED;
5.主程序
int32_t main(void)
{   RCC_Configuration();//配置RCC
    GPIO_Configuration();//配置GPIO
    UART_Configuration();//配置UART
    UART_HalfDuplexCmd(UARTy, ENABLE); //单线半双工 UARTy
    UART_HalfDuplexCmd(UARTz, ENABLE); //单线半双工 UARTz
    while(NbrOfDataToRead2--)   //UARTy -> UARTz
    {
        //UARTy发送一个字节数据
        UART_SendData_8bit(UARTy, TxBuffer1[TxCounter1++]);
        while(UART_GetFlagStatus(UARTy, UART_FLAG_TXE) == RESET);
        //UARTz 等待RC
        while(UART_GetFlagStatus(UARTz, UART_FLAG_RC) == RESET);
        UART_ClearFlag(UARTz, UART_FLAG_RC);
        RxBuffer2[RxCounter2++] = UART_ReceiveData_8bit(UARTz);
    }
    while(NbrOfDataToRead1--)//UARTz -> UARTy
    {
        //UARTz发送一个字节数据
        UART_SendData_8bit(UARTz, TxBuffer2[TxCounter2++]);
        while(UART_GetFlagStatus(UARTz, UART_FLAG_TXE)== RESET);
        //UARTy 等待RC
        while(UART_GetFlagStatus(UARTy,UART_FLAG_RC) == RESET);
        UART_ClearFlag(UARTy, UART_FLAG_RC);
        RxBuffer1[RxCounter1++] = UART_ReceiveData_8bit(UARTy);
    }
    //检查收发数据一致性
    TransferStatus1 = Buffercmp(TxBuffer1, RxBuffer2, TxBufferSize1);
    TransferStatus2 = Buffercmp(TxBuffer2, RxBuffer1, TxBufferSize2);
    if(TransferStatus1 == PASSED && TransferStatus2 == PASSED) //PASSED
    {
        //LED1亮
        PC03_SETHIGH();
    }
    else //FAILED
    {
        PC02_SETHIGH();//LED2亮
    }
    while(1)
    {
    }
}
6.测试结果:UART半双工通信方式工作正常, LED1亮。

使用特权

评论回复
沙发
duo点| | 2023-5-23 16:20 | 只看该作者

使用特权

评论回复
板凳
gaoyang9992006| | 2023-5-26 09:44 | 只看该作者
大佬不会用贴代码的框框吗注意编辑工具栏的    <>   这个符号,点一下体验体验。

使用特权

评论回复
地板
lulugo| | 2023-6-13 15:38 | 只看该作者
富莱电子的H7-TOOL开发工具可以仿真烧录芯源的单片机

使用特权

评论回复
5
两只袜子| | 2023-6-19 14:25 | 只看该作者
二楼的建议很中肯

使用特权

评论回复
6
zhanan| | 2023-8-3 11:29 | 只看该作者
发送的时候,接收是屏蔽的。如果能同时接收,可以扩展特殊用途,如线路仲裁,单线总线通信。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

40

主题

40

帖子

0

粉丝