• LL库使用


    一、前言

      LL相比较HAL占用空间小很多,执行效率更高,以后也更加的支持LL库;

    二、基础工程建立

      使用的库选择

      

    三、GPIO使用

      主要实现:拉高,拉低,取反,读取

    #ifdef defLED1
        #define LED1_ON              (LL_GPIO_SetOutputPin(LED1_GPIO_Port,LED1_Pin))
        #define LED1_OFF             (LL_GPIO_ResetOutputPin(LED1_GPIO_Port,LED1_Pin))
        #define LED1_RE              (LL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin))
        #define LED1_IN_STA   (LL_GPIO_ISInputPinSet(LED1_GPIO_Port,LED1_Pin) == GPIO_PIN_SET)   //读取电平状态,可以判断LED1是点亮还是熄灭
    #endif

    四、串口使用

      1、普通中断方式

      主要实现收到数据马上发出去

    //初始化
    void
    bsp_uartxInit(void) { LL_USART_EnableIT_RXNE(USART1); LL_USART_EnableIT_PE(USART1); } //中断调用 void LL_UARTX_PeriodElapsedCallback(USART_TypeDef *luart) { uint8_t tmp; if(luart == USART1) { if(LL_USART_IsActiveFlag_RXNE(USART1)) //检测是否接收中断 { tmp=LL_USART_ReceiveData8(USART1); //读取出来接收到的数据 LL_USART_TransmitData8(USART1,tmp); //把数据再从串口发送出去 } } }

      /**
      * @brief This function handles USART1 global interrupt.
      */
      void USART1_IRQHandler(void)
      {
        /* USER CODE BEGIN USART1_IRQn 0 */
        LL_UARTX_PeriodElapsedCallback(USART1);
        /* USER CODE END USART1_IRQn 0 */
        /* USER CODE BEGIN USART1_IRQn 1 */

        /* USER CODE END USART1_IRQn 1 */
      }

     

      2、空闲中断方式

      3、DMA空闲中断方式

    注意bsp_uartxInit();放到初始化位置,LL_DMA_UART_PeriodElapsedCallback放到用到的DMA中断里面。

    // Header:
    // File Name: 
    // Author:LQW
    // Date:2021/
    #include "bsp_uartx.h"
    
    
    #ifdef defUART1
    stuUx stuU1;
    #endif
    uint8_t  gdma_ch = 0;
    stuUx *gpUx;
    DMA_TypeDef *gDMAx;
    USART_TypeDef *gluartx;
    
    void bsp_uartxInit(void)
    {
        
        #ifdef defUART1
        
        gpUx = &stuU1;
        gDMAx = DMA1;
        gdma_ch = LL_DMA_CHANNEL_4;
        gluartx = USART1;
        LL_DMA_SetPeriphAddress(gDMAx, gdma_ch, (uint32_t)(&gluartx->TDR));//外设地址
        LL_DMA_SetMemoryAddress(gDMAx, gdma_ch, (uint32_t)gpUx->TxDataBuff);//数据地址
        LL_DMA_SetDataLength(gDMAx, gdma_ch, TX_MAX_SIZE);//
        //添加
        LL_USART_ClearFlag_TC(gluartx);
        LL_USART_EnableIT_TC(gluartx);
        
        LL_DMA_EnableIT_TC(gDMAx, gdma_ch);    
        LL_USART_EnableDMAReq_TX(gluartx);
        
        gpUx = &stuU1;
        gDMAx = DMA1;
        gdma_ch = LL_DMA_CHANNEL_5;
        gluartx = USART1;
        LL_DMA_SetPeriphAddress(gDMAx, gdma_ch, (uint32_t)(&gluartx->RDR));//外设地址
        LL_DMA_SetMemoryAddress(gDMAx, gdma_ch, (uint32_t)gpUx->RxDataIng);//数据地址
        LL_DMA_SetDataLength(gDMAx, gdma_ch, RX_MAX_SIZE);//
        LL_DMA_EnableIT_TC(gDMAx, gdma_ch);
        LL_DMA_EnableChannel(gDMAx, gdma_ch);
        LL_USART_EnableDMAReq_RX(gluartx);
        LL_USART_ClearFlag_IDLE(gluartx);
        LL_USART_EnableIT_IDLE(gluartx);
      #endif    
    }
    
    
    /**
    *@FUN:
    *@PRO:
    *@BAK:LQW
    */int LL_DMA_UART_PeriodElapsedCallback(void)
    {//
        #ifdef defUART1 
        if(LL_DMA_IsActiveFlag_GI5(DMA1))//DMA1-CH5    全局中断
        {
            if(LL_DMA_IsActiveFlag_TC5(DMA1)) //检测是否发送完成
            {
                LL_DMA_ClearFlag_TC5(DMA1);    
            }
            if(LL_DMA_IsActiveFlag_TE5(DMA1)) //检测是否发送完成
            {
                LL_DMA_ClearFlag_TE5(DMA1);    
            }
            LL_DMA_ClearFlag_GI5(DMA1); 
        }
        if(LL_DMA_IsActiveFlag_GI4(DMA1))//DMA1-CH5    全局中断
        {
            if(LL_DMA_IsActiveFlag_TC4(DMA1)) //检测是否发送完成
            {
                LL_DMA_ClearFlag_TC4(DMA1);    
            }
            if(LL_DMA_IsActiveFlag_TE4(DMA1)) //检测是否发送完成
            {
                LL_DMA_ClearFlag_TE4(DMA1);    
            }
            LL_DMA_ClearFlag_GI4(DMA1); 
        }
        #endif
        
    
        
        return 0;
    }
    
    //DMA发送
    int LL_USART_TX_DMA_EN(USART_TypeDef *luart,uint8_t *buff,uint16_t len)
    {
        #ifdef defUART1
        gpUx = &stuU1;
        gDMAx = DMA1;
        gdma_ch = LL_DMA_CHANNEL_4;
        gluartx = USART1;
        #endif
        LL_DMA_DisableChannel(gDMAx, gdma_ch);
        memcpy(gpUx->TxDataBuff,buff,len);
        LL_DMA_SetDataLength(gDMAx, gdma_ch, len);             
        LL_DMA_EnableChannel(gDMAx, gdma_ch);
        return 0;
    }
    
    /**普通发送
    *@FUN:
    *@PRO:
    *@BAK:LQW
    */int LL_USART_TX_EN(USART_TypeDef *luart,uint8_t *buff,uint16_t len)
    {//
        uint16_t i=0;
        for(i=0; i<len; i++)
        {
            LL_USART_TransmitData8(luart,buff[i]);  //把数据再从串口发送出去
            while(READ_BIT(luart->ISR,6) == 0);
        }
        return 0;
    }
    
    
    ////            LL_USART_TransmitData8(USART1,tmp);  //把数据再从串口发送出去     
    //接收回调函数
    void LL_UARTn_PeriodElapsedCallback(USART_TypeDef *luart)
    {
        uint16_t i=0;
    
    
        if(LL_USART_IsActiveFlag_IDLE(luart)) //.检测IDLE标志
        {
            #ifdef defUART1 
            if(luart == USART1)
            {
                gpUx = &stuU1;
                gDMAx = DMA1;
                gdma_ch = LL_DMA_CHANNEL_5;
            }
            #endif
            
        LL_DMA_DisableChannel(gDMAx, gdma_ch); //  
            i = LL_DMA_GetDataLength(gDMAx,gdma_ch);
        gpUx->RxlenIng = RX_MAX_SIZE-i;
    
            LL_DMA_SetDataLength(gDMAx, gdma_ch, RX_MAX_SIZE);             
            LL_DMA_EnableChannel(gDMAx, gdma_ch);
            LL_USART_ClearFlag_IDLE(luart);    
            
            LL_USART_ReceiveData8(luart);   //读取出来接收到的数据
            for(i=0; i < gpUx->RxlenIng; i++)
            {
                gpUx->RxDataBuff[i] = gpUx->RxDataIng[i];
                gpUx->RxDataIng[i] = 0;
            }
            gpUx->Rxlen = gpUx->RxlenIng;
            gpUx->RxlenIng = 0;//
            gpUx->TXRX_Sta = urRXok;//标志已经成功接收到一包等待处理
    
        }
        if(LL_USART_IsActiveFlag_TC(luart)) //.检测TC标志
        {
            #ifdef defUART1 
            if(luart == USART1)
            {
                gpUx = &stuU1;
                gDMAx = DMA1;
                gdma_ch = LL_DMA_CHANNEL_4;
            }
            #endif
            LL_USART_ClearFlag_TC(luart);    //清除TC中断  可关闭(LL_USART_DisableIT_TC) 防止反复进入TC中断
        LL_DMA_DisableChannel(gDMAx, gdma_ch); // 关闭DMA通道(LL_DMA_DisableChannel)
        }
        
    
    }
    
    
    
    
    #ifdef defUART1 
    /**打印函数
    *@FUN:
    *@PRO:
    *@BAK:
    */uint8_t U1_Printf(const char *fmt, ...)
    {
          int16_t size =0;
        
        va_list va_params;
        if(_DUGUG_ == 1 ) 
                return 0; //如果处于配置状态,不打印DEBUG数据
        
        va_start(va_params,fmt); 
        size =vsnprintf((char *)stuU1.TxDataBuff,(uint16_t)255,fmt,va_params);
        va_end(va_params);
    
        if(size != -1 )
        {
                #ifdef defU1_EN
                    U1_EN_ON;
                    stuU1.TxTim = 10;
                #else
                    
                #endif
                stuU1.Txlen = size;
                stuU1.TXRX_Sta = urTXwat;
                #ifdef defU1_OVERTIM
                stuU1.RxWaitTim = U1_TxRxOverTim;
                #endif
        }
            return 1;
    }
    
    /**
    *@FUN:
    *@PRO:
    *@BAK:
    */int U1_Printf_UINT(char *buff,int len)
    {//
        if(len >= 0)
        {
                #ifdef defU1_EN
                    U1_EN_ON;
                  stuU1.TxTim = 10;
                #else
                #endif
                memcpy(stuU1.TxDataBuff,buff,len);
                stuU1.Txlen = len;
                stuU1.TXRX_Sta = urTXwat;
                #ifdef defU1_OVERTIM
                stuU1.RxWaitTim = U1_TxRxOverTim;
                #endif
                return 0;
        }    
        return -1;
    }
    
    
    #endif
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #ifdef PRINTFX
    
    /*-------------------------------------------------*/
    /*函数名:串口1 printf函数                         */
    /*参  数:char* fmt,...  格式化输出字符串和参数    */
    /*返回值:无                                       */
    /*-------------------------------------------------*/
    
    __align(8) char Usart1_TxBuff[TX_MAX_SIZE];
    
    void Printf(char* fmt,...) 
    {  
        unsigned int i,length;
        
        va_list ap;
        va_start(ap,fmt);
        vsprintf(Usart1_TxBuff,fmt,ap);
        va_end(ap);    
        
        length=strlen((const char*)Usart1_TxBuff);        
        while((USART1->ISR&0X40)==0);
        for(i = 0;i < length;i ++)
        {            
            LL_USART_TransmitData8(USART1,Usart1_TxBuff[i]);
        }    
    }
    
    #endif
    
    
    
    
    
    
    
    
    
    /////////////////////////////////////////////////////
    C文件
    #ifndef _BSP_UARTX_H
    #define _BSP_UARTX_H
    #ifdef __cplusplus
    extern "C" {
    #endif
    #include "main.h"
    
    #define U_TEST     (1)//串口测试 1发等于收   0实际
    #define _DUGUG_    (0)//串口开关
    //#define PRINTFX    (1)
    void Printf(char* fmt,...) ;
    
    #define Ux_MAX_SIZE       (64)
    #define TX_MAX_SIZE             (Ux_MAX_SIZE-1)        //发送数据长度,最好等于
    #define RX_MAX_SIZE              (Ux_MAX_SIZE-1)      //定义最大接收字节数
    #define Ux_TxRxOverTim    (Ux_MAX_SIZE*2)
        
    #define defUART1 1
    //#define defU1_EN   1
    
    #if defined (defU1_EN) && defined (defUART1)
     #define U1_EN_ON     (LL_GPIO_SetOutputPin(USART1_EN_GPIO_Port,USART1_EN_Pin,GPIO_PIN_SET))
     #define U1_EN_OFF    (LL_GPIO_SetOutputPin(USART1_EN_GPIO_Port,USART1_EN_Pin,GPIO_PIN_RESET))
    #endif
    
    
    typedef enum
    {
        urStop,        //停止
        urIdle,        //空闲
        urRXing,    //接收中
        urRXok,      //接收完成
        urTXwat,    //有数据要发送
        urTXing,    //数据发送中
        urTXok,      //数据发送完成
        urRXwat,  //接收等待
        urErr,      //数据错误
    }UART_STA;
    
    typedef struct
    {
        UART_STA   TXRX_Sta;
    //    uint16_t   TxTim;                       //发送状态切换延时时间
    //    uint16_t   RxTim;                       //帧完成时间
    //    uint16_t   RxIdleTim;                   //最长空闲时间
    //    uint16_t   RxWaitTim;                   //等待应答
    //    uint8_t    TxDataIng[TX_MAX_SIZE];         //接收缓冲,最大USART_REC_LEN个字节. 
        uint8_t    TxDataBuff[TX_MAX_SIZE];     //接收缓冲,最大USART_REC_LEN个字节.
    //  uint8_t    RUData[2];                              //发送数据缓冲区    
        uint8_t    RxDataIng[RX_MAX_SIZE];            //发送数据缓冲区
        uint8_t    RxDataBuff[RX_MAX_SIZE];            //发送数据缓冲区
      uint8_t      Rxlen;
        uint8_t   RxlenIng;
    //  uint16_t      TxlenIng;
        uint8_t   Txlen;
        union
        {
            struct
            {
                uint8_t WordLength:1;//数据长度[0] :0- 8位;1-7位 
                uint8_t Parity:2;//奇偶校验[1:2] :00-无校验; 01-奇校验O; 11-偶校验E
                uint8_t StopBits:1;//停止位[3]:0-1位;1-2位 
                uint8_t BaudRate:4;//波特率[4-7]:0-9600; 1-19200;2-38400;3-57600; 4-115200
            }stu;
            uint8_t Da;// 1 229通讯配置:       RW
        }ComSet,ComSetO;
    }stuUx;
    
    #ifdef defUART1
    extern stuUx stuU1;
    #endif
    
    
    
    
    
    
    
    
    
    void bsp_uartxInit(void);
    void LL_UARTn_PeriodElapsedCallback(USART_TypeDef *luart);
    int LL_DMA_UART_PeriodElapsedCallback(void);
    int LL_USART_TX_DMA_EN(USART_TypeDef *luart,uint8_t *buff,uint16_t len);
    
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    ////////////////////////////////////////////////////////
    H文件

     五、IIC使用

    // Header:
    // File Name: 
    // Author:LQW
    // Date:2021/
    #include "bsp_iic.h"
    
    /****************************************************************************
    **函数名称:void I2C1_Read(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer)
    **功能概要:uint8_t driver_Addr-从器件地址, uint8_t start_Addr-从器件要读取的起始地址, 
                uint8_t number_Bytes-要读取的数据个数, uint8_t *read_Buffer-存放数据首地址
    **参数说明:无
    **函数返回:无
    ****************************************************************************/
    void I2C1_Read(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer)
    {
        uint8_t read_Num;
      uint16_t tim_dly = 25000;
        
        while(LL_I2C_IsActiveFlag_BUSY(I2C1) != RESET)
            tim_dly--;
        LL_I2C_HandleTransfer(I2C1, driver_Addr,LL_I2C_ADDRSLAVE_7BIT,1, LL_I2C_MODE_SOFTEND, LL_I2C_GENERATE_START_WRITE);
        while(LL_I2C_IsActiveFlag_TXIS(I2C1) == RESET)
            tim_dly--;
        
        LL_I2C_TransmitData8(I2C1, start_Addr);
        while(LL_I2C_IsActiveFlag_TC(I2C1) == RESET)
            tim_dly--;
        
        LL_I2C_HandleTransfer(I2C1, driver_Addr,LL_I2C_ADDRSLAVE_7BIT,number_Bytes,  LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ);
        for(read_Num = 0; read_Num < number_Bytes; read_Num++)
        {
            while(LL_I2C_IsActiveFlag_RXNE(I2C1) == RESET)
            tim_dly--;
            read_Buffer[read_Num] = LL_I2C_ReceiveData8(I2C1);
        }
    
        while(LL_I2C_IsActiveFlag_STOP(I2C1) == RESET)
            tim_dly--;
    }
    
    /****************************************************************************
    **函数名称:void I2C1_Write(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer)
    **功能概要:I2C写函数
    **参数说明:uint8_t driver_Addr-从器件地址, uint8_t start_Addr-从器件要写入的起始地址 
                uint8_t number_Bytes-要写入的数据个数, uint8_t *write_Buffer-待写入数据的起始地址
    **函数返回:无
    ****************************************************************************/
    void I2C1_Write(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer)
    {
      uint8_t write_Num;
      uint16_t tim_dly = 25000;
      
        while(LL_I2C_IsActiveFlag_BUSY(I2C1) != RESET)
            tim_dly--;
        
      LL_I2C_HandleTransfer(I2C1, driver_Addr,LL_I2C_ADDRSLAVE_7BIT, 1, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_START_WRITE);
        while(LL_I2C_IsActiveFlag_TXIS(I2C1) == RESET)
            tim_dly--;
        
      LL_I2C_TransmitData8(I2C1, start_Addr);
      while(LL_I2C_IsActiveFlag_TCR(I2C1) == RESET)
            tim_dly--;
        
      LL_I2C_HandleTransfer(I2C1, driver_Addr,LL_I2C_ADDRSLAVE_7BIT, number_Bytes, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_NOSTARTSTOP);
      for(write_Num = 0; write_Num < number_Bytes; write_Num++)
      {
        while(LL_I2C_IsActiveFlag_TXIS(I2C1) == RESET)
            tim_dly--;
        LL_I2C_TransmitData8(I2C1, write_Buffer[write_Num]);
      }
    
      while(LL_I2C_IsActiveFlag_STOP(I2C1) == RESET)
            tim_dly--;
        
    }
    ////////////////////////////////////////////////////////////
    IIC的C文件
    #ifndef _BSP_IIC_H
    #define _BSP_IIC_H
    #ifdef __cplusplus
    extern "C" {
    #endif
    #include "main.h"
    
    
    
    
    
    
    void I2C1_Read(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer);
    void I2C1_Write(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer);
    
    
    
    
    
    
    
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    ////////////////////////////////////////////////////////
    IIC的H文件

      六、定时器使用

    TIMx_Init();//初始化文件

    // Header:
    // File Name: 
    // Author:LQW
    // Date:2021/
    #include "bsp_tim.h"
    
    
    
    TIM_TypeDef *plltim_1msTim = TIM16;
    TIM_TypeDef *plltim_xxxTim = TIM17;
    
    uint32_t TxCnt[10] = {0};
    
    
    /**
    *@FUN:
    *@PRO:
    *@BAK:
    */void Loop1ms(void)
    {//
    
    }
    
    
    /**
    *@FUN:
    *@PRO:
    *@BAK:
    */void Loop10ms(void)
    {//
    
    }
    
    
    
    /**
    *@FUN:
    *@PRO:
    *@BAK:
    */void Loop100ms(void)
    {//
    
    }
    
    /**
    *@FUN:
    *@PRO:
    *@BAK:
    */void Loop1000ms(void)
    {//
        LL_IWDG_ReloadCounter(IWDG);
    }
    
    /**
    *@FUN:
    *@PRO:
    *@BAK:LQW
    */int8_t Loop10s(void)
    {//
    
    
        return 0;    
    }
    
    
    
    /**函数执行
    *@FUN:
    *@PRO:
    *@BAK:
    */void Time100usLoopProcess(void)
    {//
    
    }
    
    /**1ms中断
    *@FUN:
    *@PRO:
    *@BAK:
    */void LoopTimx1ms(void)
    {//
          Loop1ms();
          if(TxCnt[0]++ >= 10-1)
            {//10ms
                TxCnt[0] = 0;
                TxCnt[5]++;
                Loop10ms();
            }      
          if(TxCnt[1]++ >= 100-1)
            {//100m
                TxCnt[1] = 0;
                TxCnt[6]++;
                Loop100ms();
            }
          if(TxCnt[2]++ >= 1000-1)
            {//1000ms
                TxCnt[2] = 0;
                TxCnt[7]++;
                Loop1000ms();
            }
          if(TxCnt[3]++ >= 10000-1)
            {//10s
                TxCnt[3] = 0;
                TxCnt[8]++;
                Loop10s();
            }    
    }
    
    
    /**
    *@FUN:
    *@PRO:
    *@BAK:LQW
    */int TIMx_Init(void)
    {//
        LL_TIM_EnableIT_UPDATE(plltim_1msTim);//TIM更新使能
        LL_TIM_EnableCounter(plltim_1msTim);//TIM计数使能
        
        LL_TIM_EnableIT_UPDATE(plltim_xxxTim);//TIM更新使能
        LL_TIM_EnableCounter(plltim_xxxTim);//TIM计数使能
        
        return 0;
    }
    
    
    
    
    
    
    
    void TIMx_IRQHandler(TIM_TypeDef *llTimx)
    {
        if(llTimx == TIM16)
        {
            if(LL_TIM_IsActiveFlag_UPDATE(llTimx))
            {
                LoopTimx1ms();
                LL_TIM_ClearFlag_UPDATE(llTimx);    
            }
        }
        else if(llTimx == TIM17)
        {
            if(LL_TIM_IsActiveFlag_UPDATE(llTimx))
            {
                Time100usLoopProcess();
                LL_TIM_ClearFlag_UPDATE(llTimx);
            }
        }
        
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    /////////////////////////////////////////////////////
    定时器C文件
    #ifndef _BSP_TIM_H
    #define _BSP_TIM_H
    #ifdef __cplusplus
    extern "C" {
    #endif
    #include "main.h"
    
    
    
    
    
    
    
    
    
    
    
    
    
    int TIMx_Init(void);
    void TIMx_IRQHandler(TIM_TypeDef *llTimx);
    
    
    
    
    
    
    
    
    
    
    
    
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    ////////////////////////////////////////////////////////
    定时器H文件
  • 相关阅读:
    centos 7安装配置vsftpd
    lvs和haproxy机器必须注意的三个参数
    用python 脚本实现zabbix对java端口报警
    git的下载地址
    看的一篇很好的博客
    学习内容
    数组一些用法
    dom
    dom1
    for的基础
  • 原文地址:https://www.cnblogs.com/luckytimor/p/14840941.html
Copyright © 2020-2023  润新知