串口驱动开发

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 串口驱动开发

实验芯片:stm32f103CBT6

串口3初始化收发函数

初始化函数

void Initial_UART3(u32 baudrate)
{
     GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_Init(GPIOB, &GPIO_InitStructure);    

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
      GPIO_Init(GPIOB, &GPIO_InitStructure);
      
    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    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(USART3, &USART_InitStructure); 
  USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); 

      USART_Cmd(USART3, ENABLE);
    U3NVIC_Configuration();
}

做初始化函数有点小插曲
在这里插入图片描述
RCC_APB2Periph_GPIOB 的时钟 放到了 RCC_APB1PerphClockCmd()的函数中了
也就是说 RCC_APB2Periph 时钟总线用 RCC_APB1Perph 的使能函数使能了。这是不对的 。

造成的结果是串口3可以接收到数据,但是不能发送。 这个结果不知道是为什么。

中断优先级分组

void U3NVIC_Configuration(void)
{
   NVIC_InitTypeDef NVIC_InitStructure; 
   /* Enable the USART3 Interrupt */

     NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);    
    
   //Enable DMA1 Channel3 Interrupt 
   NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);    
}

串口3DMA配置

void DMA_UART3Config(void)
{ 

    DMA_InitTypeDef DMA_InitStructure;                    
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);   
    
    DMA_DeInit(DMA1_Channel3);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)SRC_USART3_DR;
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART3_DMA_Recieve_Buf;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;            

    DMA_InitStructure.DMA_BufferSize = UART3_RECIEVE_LENDTH;                 
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;        

    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;        

    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;    
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

    DMA_Init(DMA1_Channel3, &DMA_InitStructure);    
    DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);    
    DMA_Cmd(DMA1_Channel3, ENABLE);

    USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE); 
}

串口3发送函数

void UART3_Put_Char(unsigned char DataToSend)
{
    USART_SendData(USART3, DataToSend);

      while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET){}
}

void UART3_Send_Buf(unsigned char *buf,unsigned char len)
{
    unsigned char i ;
    for(i=0;i<len;i++,buf++)
    {
        UART3_Put_Char(*buf);
    }
}

串口3 接收函数

void DMA1_Channel3_IRQHandler(void)
{
        uint16_t length;
   if(DMA_GetITStatus(DMA1_IT_TC3)==SET) 
   { 
         DMA_Cmd(DMA1_Channel3, DISABLE); //¹Ø±ÕDMA£¬·ÀÖ¹´¦ÀíÆÚ¼äÓÐÊý¾Ý  
         length = UART3_RECIEVE_LENDTH - DMA_GetCurrDataCounter(DMA1_Channel3);  
         if(length != 0)
         {
         }            
        DMA_SetCurrDataCounter(DMA1_Channel3, UART3_RECIEVE_LENDTH);  
        DMA_Cmd(DMA1_Channel3, ENABLE);         
        DMA_ClearITPendingBit(DMA1_IT_TC3); 
   }
}
  • [x] 测试这个函数需不需要

可以不要


//------------------------------------------------------
void USART3_IRQHandler(void)
{
    uint8_t data;
    uint16_t length,check;
    
  if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)//¿ÕÏÐÖжÏ
  {        
        DMA_Cmd(DMA1_Channel3, DISABLE); 
        data = data;
        data = USART3->SR;  
        data = USART3->DR;  
        length = UART3_RECIEVE_LENDTH - DMA_GetCurrDataCounter(DMA1_Channel3);  
 
        if(length != 0)
        {
                                            
        }        
        DMA_SetCurrDataCounter(DMA1_Channel3, UART3_RECIEVE_LENDTH);  
        DMA_Cmd(DMA1_Channel3, ENABLE);     //´ò¿ªDMA,              
        DMA_ClearITPendingBit(DMA1_IT_TC3);         
    }
}

加入打印函数 重定向至串口1

记住就行, 直接就能用


#if 1// 串口1打印
#pragma import(__use_no_semihosting)                        
struct __FILE 
{ 
    int handle; 
}; 

FILE __stdout;        
_sys_exit(int x) 
{ 
    x = x; 
} 
int fputc(int ch, FILE *f)
{      
    while((USART1->SR&0X40)==0);//Ñ­»··¢ËÍ,Ö±µ½·¢ËÍÍê±Ï   
    USART1->DR = (u8) ch;      
    return ch;
}
#endif 

需要打开? 实际测试 不打开也没事
在这里插入图片描述

传感器数据解析

传感器发送的数据协议

协议
在这里插入图片描述
在这里插入图片描述

以解析欧拉角x为例

// ´«¸ÐÆ÷½â¶ÁµÄÅ·À­½Ç
typedef struct 
{
  float x;
    float y;
    float z;    
}Euler_T;

typedef struct 
{
  uint8_t    x[4];
  uint8_t    y[4];
  uint8_t    z[4];
}Euler_32bit_T;
            if     (USART3_DMA_Recieve_Buf[0]== 0x3A&&USART3_DMA_Recieve_Buf[1]== 0x01&&USART3_DMA_Recieve_Buf[2]== 0x00&&
                    USART3_DMA_Recieve_Buf[3]== 0x09&&USART3_DMA_Recieve_Buf[4]== 0x00&&USART3_DMA_Recieve_Buf[5]== 0x50&&
                    USART3_DMA_Recieve_Buf[6]== 0x00 )            
            {        
                  // 传感器32位数据 低位在前
                Euler_32bit.x[0]  =   USART3_DMA_Recieve_Buf[63];
                Euler_32bit.x[1]  =   USART3_DMA_Recieve_Buf[64];
                Euler_32bit.x[2]  =   USART3_DMA_Recieve_Buf[65];
                Euler_32bit.x[3]  =   USART3_DMA_Recieve_Buf[66];
                
                Euler.x = *((float*)Euler_32bit.x);    
            }                        

手册上写了 数据是低位在前的
在这里插入图片描述
但是在通过 指针然后强制转换时 将数据 改成高位在前后不对了

  • [ ] 可能指针强制转换就是低位在前?也可能数据发的就是高位在前
  • [ ] 反正换了下顺序对了

Euler.x = ((float)Euler_32bit.x)

打印测试

 printf("Euler.x = %f \r\n ",        Euler.x/DEG2RAD);

在这里插入图片描述
按轴移动后没有问题

把其它变量也解算出来

和以解析欧拉角x 一样,解析了 欧拉角y 欧拉角z
其中x和y 静态飘移 较小 z轴飘移很大 向一方向一直飘 可能是没有 校准的原因

//// 传感器线加速度数据
typedef struct 
{
  float x;
    float y;
    float z;    
}LinearAcceleration_T;

typedef struct 
{
  uint8_t    x[4];
  uint8_t    y[4];
  uint8_t    z[4];
}LinearAcceleration_32bit_T;;
         LinearAcceleration_32bit.x[0] = USART3_DMA_Recieve_Buf[75];
         LinearAcceleration_32bit.x[1] = USART3_DMA_Recieve_Buf[76];
         LinearAcceleration_32bit.x[2] = USART3_DMA_Recieve_Buf[77];
         LinearAcceleration_32bit.x[3] = USART3_DMA_Recieve_Buf[78];
                    
         LinearAcceleration_32bit.y[0] = USART3_DMA_Recieve_Buf[79];
         LinearAcceleration_32bit.y[1] = USART3_DMA_Recieve_Buf[80];
         LinearAcceleration_32bit.y[2] = USART3_DMA_Recieve_Buf[81];
         LinearAcceleration_32bit.y[3] = USART3_DMA_Recieve_Buf[82];                    
                    
         LinearAcceleration_32bit.z[0] = USART3_DMA_Recieve_Buf[83];
         LinearAcceleration_32bit.z[1] = USART3_DMA_Recieve_Buf[84];
         LinearAcceleration_32bit.z[2] = USART3_DMA_Recieve_Buf[85];
         LinearAcceleration_32bit.z[3] = USART3_DMA_Recieve_Buf[86];
          
          LinearAcceleration.x= *((float*)LinearAcceleration_32bit.x);
          LinearAcceleration.y= *((float*)LinearAcceleration_32bit.y);
          LinearAcceleration.z= *((float*)LinearAcceleration_32bit.z);

打印加速度数据不能有延迟
在这里插入图片描述

做传感器碰撞检测

简答做就根据 欧拉角和加速度判断
变化大于阈值时 则 串口1发送当前值

void CollisionCheck(float LinearAccelerationThreshold, float EulerThreshold)
{  
   
   if (fabs(Euler_Last.x- Euler.x)>LinearAccelerationThreshold  &&fabs(Euler_Last.y- Euler.y)>LinearAccelerationThreshold&&fabs(Euler_Last.z- Euler.z)>LinearAccelerationThreshold 
           &&fabs(LinearAcceleration_Last.x- LinearAcceleration.x)>EulerThreshold 
         &&fabs(LinearAcceleration_Last.x- LinearAcceleration.x)>EulerThreshold
                                                                         )
     {
          Euler_Last.x  =  Euler.x ;
            Euler_Last.y  =  Euler.y ;
            Euler_Last.z  =  Euler.z ;
     
            LinearAcceleration_Last.x = LinearAcceleration.x;
            LinearAcceleration_Last.y = LinearAcceleration.y;
            LinearAcceleration_Last.z = LinearAcceleration.z;
         
         
         
            UART1_ALARM_DATA[0] = 0x01;
            UART1_ALARM_DATA[1] = LinearAcceleration_32bit.x[0];
            UART1_ALARM_DATA[2] = LinearAcceleration_32bit.x[1];         
            UART1_ALARM_DATA[3] = LinearAcceleration_32bit.x[2];         
            UART1_ALARM_DATA[4] = LinearAcceleration_32bit.x[3];
         
            UART1_ALARM_DATA[5] = LinearAcceleration_32bit.y[0];
            UART1_ALARM_DATA[6] = LinearAcceleration_32bit.y[1];
            UART1_ALARM_DATA[7] = LinearAcceleration_32bit.y[2];
            UART1_ALARM_DATA[8] = LinearAcceleration_32bit.y[3];
         
            UART1_ALARM_DATA[9] =  Euler_32bit.x[0];
            UART1_ALARM_DATA[10] = Euler_32bit.x[1];
            UART1_ALARM_DATA[11] = Euler_32bit.x[2];                
            UART1_ALARM_DATA[12] = Euler_32bit.x[3];                
            UART1_ALARM_DATA[13] = Euler_32bit.y[0];                
            UART1_ALARM_DATA[14] = Euler_32bit.y[1];                
            UART1_ALARM_DATA[15] = Euler_32bit.y[2];                
            UART1_ALARM_DATA[16] = Euler_32bit.y[3];
            UART1_ALARM_DATA[17] = Euler_32bit.z[0];                
            UART1_ALARM_DATA[18] = Euler_32bit.z[1];                
            UART1_ALARM_DATA[19] = Euler_32bit.z[2];                
            UART1_ALARM_DATA[20] = Euler_32bit.z[3];
            
            UART1_Send_Buf(UART1_ALARM_DATA,21);
         
         
     }


}
相关文章
|
7月前
嵌入式开发板串口驱动框架
嵌入式开发板串口驱动框架
67 0
STM32串口编程基础知识讲解
STM32串口编程基础知识讲解
106 0
|
7月前
LabVIEW研华USB 4716 例程与相关资料
LabVIEW研华USB 4716 例程与相关资料
50 0
|
缓存 Linux 定位技术
嵌入式Linux系列第7篇:操作UART
嵌入式Linux系列第7篇:操作UART
|
XML 测试技术 网络安全
开发工具:USB转IIC/I2C/SPI/UART适配器模块可编程开发板
总的思路是通过USB或者UART接口发送一些协议字符串,由模块转换成上面几种接口的硬件时序电信号,实现与这几种接口芯片、设备的快速测试。 首先声明一下,大家都是搞硬件开发的,这几种接口当然是很简单的事,但有些时候对于一个新的设备或者芯片的测试,有个现成的工具当然更顺手,节省时间,也更可靠嘛。
|
XML 测试技术 网络安全
开发调试工具:可编程USB转IIC/I2C/SPI/UART适配器模块开发板
发个方便测试I2C、SPI、1Wire接口的工具模块 总的思路是通过USB或者UART接口发送一些协议字符串,由模块转换成上面几种接口的硬件时序电信号,实现与这几种接口芯片、设备的快速测试。
|
XML 测试技术 网络安全
开发调试工具:可编程 USB 转串口适配器开发板
首先声明一下,大家都是搞硬件开发的,这几种接口当然是很简单的事,但有些时候对于一个新的设备或者芯片的测试,有个现成的工具当然更顺手,节省时间,也更可靠嘛。
|
XML 传感器 测试技术
开发调试工具:USB转IIC/I2C/SPI/UART适配器模块可编程开发板
发个方便测试I2C、SPI、1Wire接口的工具模块 总的思路是通过USB或者UART接口发送一些协议字符串,由模块转换成上面几种接口的硬件时序电信号,实现与这几种接口芯片、设备的快速测试。 首先声明一下,大家都是搞硬件开发的,这几种接口当然是很简单的事,但有些时候对于一个新的设备或者芯片的测试,有个现成的工具当然更顺手,节省时间,也更可靠嘛。
开发调试工具:USB转IIC/I2C/SPI/UART适配器模块可编程开发板