基于HC32F005一主多从UARTX通信

多机通信(HCF005)

  1. UARTX实现多机通信

一主多从,主机发送地址,从机识别成功后,向主机发送数据。

  • 通信过程

UARTx_SCON.SM2 置“1”, 可开启多机通讯位。UARTx_SCON.SM2置“0”, 可关闭多机通讯位。

开启多机通讯后,发送数据时,主机可以通过 UARTx_SCON.TB8 来区分当前帧
是地址帧(UARTx_SCON.TB8=1)还是数据帧(UARTx_SCON.TB8=0)。接收数据时,
从机会忽略 RB8 位(第 9 位) 为“0”的当前接收帧。

  • 当为数据帧时,该帧数据不会存入到从机的 UARTx_SBUF 寄存器中,从机也不会产生接收中
    断。
     
  • 当为地址帧时,由于多机通讯中自动地址识别功能已开启,使得从机可以检测接收到的地址与
    其自身地址是否相符合。(从机开启多机通信,则开启了自动识别地址功能)

当从机地址相符合,从机会对 UARTx_SCON.RB8 置“1”, UARTx_ISR.RI 置“1”。

从机软件看到 UARTx_SCON.RB8=1 并且 UARTx_ISR.RI=1 后,将 UARTx_SCON.SM2 位清“0”,接受数据帧。(UARTx_SCON.SM2 位清“0”,似乎只能软件请零;但是因为所实现功能为从机地址识别成功后,向主机发送数据,而不是接受主机数据,所以此处SM2 位清“0”与否均可向主机发送数据。但主机作为接收方,必须SM2 位清“0”才能接受数据。

如果地址不符合,从机硬件保持 UARTx_SCON.RB8 和UARTx_ISR.RI 为“0”,软件保持 UARTx_SCON.SM2 位为“1”,继续处于地址监听状态。

  • 给定地址

UART 设 备 的 UARTx_SADDR 寄 存 器 用 来 表 示 自 己 的 设 备 给 定 地 址 ,
UARTx_SADEN 寄 存 器 是 地 址 掩 码 , 可 以 用 来 定 义 地 址 中 的 无 关 位 。当
UARTx_SADEN 的某一位为“0”, 表示该位地址为无关位, 也就是说在地址匹配过程
中,该位地址不参与地址匹配。

即SADDR=0X10(从机地址为0X10),SADEN =0X01,只识别最低位有效,无论地址0X20,0X30,,,,都认为有效;SADEN =0X0F,则识别地址时,低四位均要比较;SADEN =0XFF,则识别地址8位。

  • 具体步骤、代码

  • 配置串口模式位2/3,其余正常配置。
  • 主从均开启多机模式(UARTx_SCON.SM2 置“1”),主机先发送地址,随后关闭多机模式UARTx_SCON.SM2 置“0”)。
  • 从机成功识别地址,准备向主机发送数据前,不需要关闭多机模式
  • 注意,此时正常通信,TB8位也可以作为奇偶校验位来使用。Uart_SetTb8(M0P_UART1,UartEven,u8RxData[0])该函数设置奇偶校验位。

主机代码:

```c
#include <stdio.h>
uint8_t ARR1= 0X10,ARR2= 0X11;//从机地址

int main(void) {

    App_ClkCfg();
    App_UartInit();
    while(1)
    {
        delay1ms(1000);
        RxData[1] = Uart_SendAddressFrame(M0P_UART1, ARR1);
        RxData[2] = Uart_SendAddressFrame(M0P_UART1, ARR2);
    }
}

//串口配置

#include "usart.h"
#include "uart.h"
#include "bt.h"
#include <stdio.h>

extern uint16_t RxData[5];
extern uint8_t RxFlag;


/*****串口波特率设置***/
static void _UartBaudCfg(void)
{
    uint16_t timer=0;

    stc_uart_baud_cfg_t stcBaud;
    stc_bt_cfg_t stcBtCfg;

    DDL_ZERO_STRUCT(stcBaud);
    DDL_ZERO_STRUCT(stcBtCfg);

    
    Sysctrl_SetPeripheralGate(SysctrlPeripheralBt,TRUE);
    Sysctrl_SetPeripheralGate(SysctrlPeripheralUart1,TRUE);     //

    stcBaud.bDbaud  = 0u;
    stcBaud.u32Baud = 115200;
    stcBaud.enMode  = UartMode3; 
    stcBaud.u32Pclk = Sysctrl_GetPClkFreq(); 
    timer = Uart_SetBaudRate(M0P_UART1, &stcBaud);      //

    stcBtCfg.enMD = BtMode2;
    stcBtCfg.enCT = BtTimer;
    Bt_Init(TIM1, &stcBtCfg);
    Bt_ARRSet(TIM1,timer);
    Bt_Cnt16Set(TIM1,timer);
    Bt_Run(TIM1);

}

/*****串口初始化***/
void App_UartInit(void)
{
    stc_uart_cfg_t  stcCfg;
  
    _UartBaudCfg();

    stcCfg.enRunMode = UartMode3;
    Uart_Init(M0P_UART1, &stcCfg);
    
//    M0P_UART1->SCON_f.SM2 = TRUE; 
//    M0P_UART0->SCON_f.TB8 = 1;
//    Uart_EnableIrq(M0P_UART1, UartRxIrq);   //使能接受中断
    Uart_ClrStatus(M0P_UART1, UartRC);
    EnableNvic(UART1_IRQn, IrqLevel2, TRUE);

}

/*****串口1中断服务函数***/
void Uart1_IRQHandler(void)
{
    if(TRUE == Uart_GetStatus(M0P_UART1, UartRC))
    {
        Uart_ClrStatus(M0P_UART1, UartRC);

        RxData[1] = Uart_ReceiveData(M0P_UART1);
        RxFlag=1;
        arr++;

    }

}


/***带有地址帧发送数据    中断***/
uint8_t Uart_SendAddressFrameIT(M0P_UART_TypeDef* UARTx, uint8_t address)
{
//    uint8_t u8RxDate = 0;
    UARTx->SCON_f.SM2 = TRUE;
    UARTx->SCON_f.TB8 = 1;    
    Uart_SendDataPoll(UARTx,address);
    delay10us(1);
    UARTx->SCON_f.SM2 = FALSE;
    
    if(UARTx->ISR_f.FE ==1)
        UARTx->ISR_f.FE =0;

}
 
/***带有地址帧发送数据    无中断  使用该函数关中断***/
uint8_t Uart_SendAddressFrame(M0P_UART_TypeDef* UARTx, uint8_t address)
{
    uint8_t u8RxDate = 0;
    
    UARTx->SCON_f.SM2 = TRUE;
    UARTx->SCON_f.TB8 = 1;    
    Uart_SendDataPoll(UARTx,address);
    delay10us(1);
    UARTx->SCON_f.SM2 = FALSE;
    if(UARTx->ISR_f.FE ==1)
        UARTx->ISR_f.FE =0;
    while(UARTx->ISR_f.RI == 0){;}
    u8RxDate = Uart_ReceiveData(UARTx);
    Uart_ClrStatus(UARTx, UartRC);      
    return u8RxDate;   
}   


/****系统时钟配置***/
//系统时钟配置
static void App_ClkCfg(void)
{
    stc_sysctrl_clk_cfg_t stcCfg;

    ///< 时钟初始化前,优先设置要使用的时钟源:此处设置RCH为24MHz(默认值为4MHz)
    Sysctrl_SetRCHTrim(SysctrlRchFreq22_12MHz);

    ///< 选择内部RCH作为HCLK时钟源;
    stcCfg.enClkSrc    = SysctrlClkRCH;
    ///< HCLK SYSCLK
    stcCfg.enHClkDiv   = SysctrlHclkDiv1;
    ///< PCLK 为HCLK
    stcCfg.enPClkDiv   = SysctrlPclkDiv2;
    ///< 系统时钟初始化
    Sysctrl_ClkInit(&stcCfg);
}
    



从机代码:

识别地址成功,从机会对RB8 置“1”,RI 置“1”。是否硬件清零不知,所以软件清零。

从机主函数:

M0P_UART1->SCON_f.SM2 = TRUE;重新开启多机通信。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值