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 /////////////////////////////////////////////////////
#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 ////////////////////////////////////////////////////////
五、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--; } ////////////////////////////////////////////////////////////
#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 ////////////////////////////////////////////////////////
六、定時器使用
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); } } } /////////////////////////////////////////////////////
#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 ////////////////////////////////////////////////////////

浙公網安備 33010602011771號