大不列颠呆毛狼184 2023-12-28 17:31 采纳率: 66.7%
浏览 11
已结题

STM32F4实现多机通信

我想实现使用STM32F4单片机之间的多机通信,目前完成两块单片机直接的收发实验。
我定义的通信协议为“头文件 地址 数据 累加校验”的数据帧,从机接受到数据成功返回给主机0x01,如果数据错误返回0xFF,地址不匹配不返回。
我现在是想添加一块单片机作为从机加入通信,碰见了情况,我可以实现主机发送数据,从机可以顺利接受进行处理,也就是一对多通信,从机却无法返回给主机数据,也就是多对一通信。
请问这个操作在一条串口通道上是可以实现的吗?如果可以的话我是需要添加什么新的配置吗?
以下是我主机与从机的串口配置
主机

void usart_init(u32 bound){
   //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能UART4时钟
 
    //串口4对应引脚复用映射
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA0复用为UART4
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA1复用为UART4
    
    //UART4端口配置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA0与GPIOA1
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    //速度50MHz
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
    GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA0,PA1

   //USART1 初始化设置
    USART_InitStructure.USART_BaudRate = bound;//波特率设置
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;    //收发模式
  USART_Init(USART1, &USART_InitStructure); //初始化串口1
    
  USART_Cmd(USART1, ENABLE);  //使能串口1 
    
    //USART_ClearFlag(USART1, USART_FLAG_TC);
    
//#if EN_USART1_RX    
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断

    //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口4中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;        //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器、

//#endif
    
}
void USART1_IRQHandler(void)                    //串口1中断服务程序
{
    u8 res;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
            {
                res = USART_ReceiveData(USART1);

                USART_SendData(UART4,res);//返回数据给PC

        }
    
} 

从机

void uart_init(u32 bound){
   //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
 
    //串口4对应引脚复用映射
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1
    
    //USART1端口配置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    //速度50MHz
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; //上拉
    GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10

   //USART1 初始化设置
    USART_InitStructure.USART_BaudRate = bound;//波特率设置
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;    //收发模式
  USART_Init(USART1, &USART_InitStructure); //初始化串口1
    
  USART_Cmd(USART1, ENABLE);  //使能串口1 
    
  USART_ClearFlag(USART1, USART_FLAG_TC);
    
//#if EN_USART1_RX    
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断

    //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;        //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器、

//#endif
    
}




void USART1_IRQHandler(void)                    //串口1中断服务程序
{
    static uint8_t index = 0;
  u8 Res,address1,address2;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0xEB起始)
    {
current_time = SysTick->VAL;    
        Res =USART_ReceiveData(USART1);//(USART1->DR);    //读取接收到的    
//        USART_SendData(USART1,Res);
      if (Res == START_FRAME && index == 0) {
        USART_RX_BUF[index] = Res;
        index++;
    } else if (index > 0 && index < USART_REC_LEN - 1) {
        USART_RX_BUF[index] = Res;
        checksum += Res;      // 累加校验
        index++;
    } else if (index == USART_REC_LEN - 1) {
        USART_RX_BUF[index] = Res;
     if (checksum == Res) // 校验通过,执行相应操作
         {   
              address1 = read_1234();
             if(USART_RX_BUF[1] == address1)
                 {
                     address2 = read_5678();
                     if(USART_RX_BUF[2] == address2)
                         {
                            USART_SendData(USART1,0x01);       
                            }
                    }
         } else {
                    USART_SendData(USART1,0xFF);        // 校验失败,执行相应操作
        }
        index = 0; // 重置索引和校验和
        checksum = 0;
    } else {
                USART_SendData(USART1,0xFF);        // 其他情况,可能是帧结构错误,进行相应处理
        index = 0; // 重置索引和校验和
        checksum = 0;
    }

        
  } 
    
    

    
   } 



这是我的硬件连接

img

  • 写回答

2条回答 默认 最新

  • mlem_init 2023-12-28 17:35
    关注

    是可以实现的,但由于你用的串口通信,所以你要将时序定义得清楚。主机发出后,从机都会收到,但只能有一个回,不可以同时回,不然总线会冲突

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 1月5日
  • 已采纳回答 12月28日
  • 创建了问题 12月28日

悬赏问题

  • ¥66 换电脑后应用程序报错
  • ¥50 array数据同步问题
  • ¥15 pic16F877a单片机的外部触发中断程序仿真失效
  • ¥15 Matlab插值拟合差分微分规划图论
  • ¥15 keil5 target not created
  • ¥15 C/C++数据与算法请教
  • ¥15 怎么找志同道合的伙伴
  • ¥20 如何让程序ab.eXe自已删除干净硬盘里的本文件自己的ab.eXe文件
  • ¥50 爬虫预算充足,跪巨佬
  • ¥15 滑块验证码拖动问题悬赏