STM32使用LIN时USART2只收不发

使用STM32F1发送和接收LIN,配置的USART2可以正常接收,但是无法发送,这是啥情况啊!!研究2天了

LIN.c

#include "stm32f10x.h"
#include "lin.h"
#include "dsq.h"
#include "LED.h"
  int i;
    int btl;
    u16 temp;
         u8 a;
void GPIO_Configuration(void)
{
    
    GPIO_InitTypeDef GPIO_InitStructure;
    /*配置LED对应位IO口*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;      //复用推挽输出              
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出              
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,ENABLE);//复位串口2
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,DISABLE);//停止复位

}

/*******************************************************************************
* Function Name  : NVIC_Configuration
* Description    : Configures the nested vectored interrupt controller.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void NVIC_Configuration(void)
{ 
    NVIC_InitTypeDef NVIC_InitStructure;

      /* Configure the NVIC Preemption Priority Bits */  
      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);              //中断分组0

    /* enabling interrupt */
      NVIC_InitStructure.NVIC_IRQChannel=USART2_IRQn;              //配置中断通道
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;    //先占中断优先级
       NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;           //从占中断优先级
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //中断使能
      NVIC_Init(&NVIC_InitStructure);                              //中断初始化
}
void Uart2_Lin_Configuration(void)                               //LIN初始化
{
    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate =18000;                                       //波特率19.2千比特
    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(USART2, &USART_InitStructure);                                         //初始化串口2寄存器
    USART_LINBreakDetectLengthConfig(USART2,USART_LINBreakDetectLength_11b);          //11位中断检测
    USART_LINCmd(USART2,ENABLE);                                                      //使能LIN模式

    USART_Cmd(USART2,ENABLE);                                                         //使能串口通信
    USART_ITConfig(USART2, USART_IT_RXNE,DISABLE);                                     //串口接收中断关闭
    USART_ITConfig(USART2, USART_IT_TXE, DISABLE);                                    //串口发送中断关闭
    USART_ITConfig(USART2, USART_IT_LBD, ENABLE);                                     //LIN中断开启
}      
    void send(u8 dlc,u8 pid,u8 sid)                                                    //LIN主机发送程序
{
    u8   Crc = 0;
    u16  TempData = 0;
    USART_ClearITPendingBit(USART2, USART_IT_TXE);                                   //清除发送标志
        USART_SendData(USART2,0xFF);                                                         //总线高电平
       TempData = (dlc&0x03) <<4;        TempData |= (pid&0x0f);                          //标识符校验
      Crc = (~(BIT(TempData,1)^BIT(TempData,3)^BIT(TempData,4)^BIT(TempData,5)))<<7;
    Crc |= (BIT(TempData,0)^BIT(TempData,1)^BIT(TempData,2)^BIT(TempData,4))<<6;        
      TempData |= Crc;     
      USART_SendBreak(USART2);                                                             //发送间隔场   
    USART_SendData(USART2,0x55);                                                     //发送同步场
      while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);                      //确认发送完成
      USART_SendData(USART2,TempData);                                                   //发送标识符
      while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); 
   USART_SendData(USART2,0xe2);                                                         //发送数据
      while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); 
      USART_SendData(USART2,0x0a);
        while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); 
         USART_SendData(USART2,0x00);
        while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); 
         USART_SendData(USART2,0xf5);
        while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); 
}
void USART2_IRQHandler(void)                                                         //USART2中断服务函数
{  

  if(USART_GetITStatus(USART2, USART_IT_LBD) != RESET)                               //检测是否收到间隔场
    {

        USART_ClearITPendingBit(USART2,USART_IT_LBD);                                      //清理中断标志
        USART_ITConfig(USART2, USART_IT_LBD, DISABLE);                                    //关闭间隔场中断
        chaxun();                                                                        //与同步场同步  
        USART_ITConfig(USART2, USART_IT_RXNE,ENABLE);                                     //开启数据接收中断

    }
 if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)                               //检测是否收到数据
    {

        a=USART_ReceiveData(USART2);                                                      //读取数据
        USART_ClearITPendingBit(USART2,USART_IT_RXNE);                                      //清理中断标志位
        if(a==0x73)//动作ID,ID等于0x33  
        {            
//            USART_SendData(USART2,0x55);
            LED1_Turn();
            
        }

        if(a==0x43)//反馈ID,ID等于0x03                            
            USART_SendData(USART2,0x55);        

    }
        

        
  if(USART_GetITStatus(USART2, USART_IT_TXE) != RESET)                                //是否发生发送中断
          USART_ClearITPendingBit(USART2,USART_IT_TXE);                                 //清理中断标志位
}

void fasong(void)                                                                      //数据发送程序
{
    USART_ITConfig(USART2, USART_IT_RXNE,DISABLE);                                     //关闭数据接收中断
    GPIO_SetBits(GPIOB,GPIO_Pin_6); 
    USART_ITConfig(USART2, USART_IT_TXE, ENABLE);                                      //使能发送中断
    USART_ClearITPendingBit(USART2, USART_IT_TXE);                                        //清除发送标志        
    USART_SendData(USART2,0x0a);                                                       //发送数据
    while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);                        //确认发送是否完成
    USART_SendData(USART2,0x00);      
    while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);  
    USART_SendData(USART2,0x13);      
    while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); 
    USART_ITConfig(USART2, USART_IT_TXE, DISABLE);                                    //串口发送中断关闭
    USART_ITConfig(USART2, USART_IT_LBD, ENABLE);                                     //开启间隔场检测中断

}    

void chaxun()                                                                          //同步场同步程序
{
        TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );
        while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));                                    //读取IO口
        while(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
        TIM_SetCounter(TIM3, 0);                                                         //0定时器3                 
        while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
        while(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
        while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
        while(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
        while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
        while(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
        while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
        while(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
        temp=TIM_GetCounter(TIM3);                                                             //读取定时器3数值
        TIM_SetCounter(TIM3, 0);
        TIM_ITConfig(TIM3,TIM_IT_Update,DISABLE );
        btl=360000/temp;
        btl=btl*8;
        USART_InitTypeDef USART_InitStructure;
        USART_InitStructure.USART_BaudRate =btl;                                       //波特率19.2千比特
        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(USART2, &USART_InitStructure);                                                //USART2使能
        GPIO_SetBits(GPIOB,GPIO_Pin_6);
    
}

dsq.c

#include "stm32f10x.h"
#include "dsq.h"
#include "lin.h"



void RCC1_Configuration(void)  
{  
    RCC_DeInit();                                         //时钟控制器全部设为默认值
  
    RCC_HSICmd(ENABLE);                                   //使能内部高速晶振
    while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);   //等待内部高速晶振准备就绪
     
    RCC_HCLKConfig(RCC_SYSCLK_Div1);                       //设置AHB时钟等于系统时钟
    RCC_PCLK1Config(RCC_HCLK_Div2);                        //设置APB1时钟等于HCLK/2时钟
    RCC_PCLK2Config(RCC_HCLK_Div1);                        //设置APB2时钟等于HCLK时钟
      
    RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9);    //设置PLL为内部系统时钟为36MHZ(8/2*9)
    RCC_PLLCmd(ENABLE);
    
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);     //等待PLL时钟准备就绪
  
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);              //设置PLL时钟为系统时钟源
    while(RCC_GetSYSCLKSource() != 0x08);                   //返回系统所用时钟源确认为内部高速晶振,8M晶振。
    /* GPIO for CAN and GPIO for LEDs clock enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO  | RCC_APB2Periph_GPIOB| 
                           RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA |
                         RCC_APB2Periph_GPIOC, ENABLE);      //使能由APB2时钟控制的外设中的PA,PB,PC和复用IO端口
//    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    /* CAN1 Periph clock enable */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);      //使能由APB1时钟控制的外设中的USART2端口

    //开启SysTick中断
    SysTick_Config(36000);                                             //启动

}  
void SysTick_Handler(void) //系统滴答定时器中断服务函数
    {
       nTime--;
    }

void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

    //定时器TIM3初始化
    TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值    
    TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
 
    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断//

    //中断优先级NVIC设置
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4;  //从优先级0级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器 


    TIM_Cmd(TIM3, ENABLE);  //使能TIMx                     
}
//定时器3中断服务程序
void TIM3_IRQHandler(void)   //TIM3中断
{
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
        {
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);  //清除TIMx更新中断标志 
        }
    }


将发送中断给关掉,发送中断这里使用应该是不正确的!

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 以下回答来自chatgpt:

    由于你没有提供完整的代码文件,无法确定你的问题出在哪里。但是下面是一些可能导致USART2无法发送LIN数据的常见问题和解决方案。

    1.USART2的时钟使能未配置: - 确保你已经在RCC寄存器中使能了USART2的时钟。应该是RCC->APB1ENR |= RCC_APB1ENR_USART2EN; 这段代码。

    2.USART2的引脚配置有误: - 确保你已经正确地配置了USART2的引脚。根据你的具体硬件连接,你可能需要将相应的引脚设置为USART2的功能。通常,你可能需要配置GPIO的模式和模式寄存器来设置引脚功能和输出类型。根据你的需求,可能需要选择推挽输出或开漏输出模式,确保引脚与外部设备正确连接。

    3.USART2的发送函数未正确调用: - 确保你使用了正确的发送函数来发送LIN数据。通常,你需要调用USART_SendData函数,并将数据写入USART_DR寄存器来发送数据。发送函数的代码可能类似于这样:

    void USART2_SendData(uint8_t data) {
        while(!(USART2->SR & USART_SR_TXE)); //等待发送寄存器为空
        USART2->DR = (data & (uint16_t)0x01FF); //将数据写入发送寄存器
    }
    

    请尝试检查以上几个问题,并根据需要进行更正。如果问题仍然存在,请提供更多的代码和错误信息,以便我们更好地帮助你解决问题。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^