HAL库代码基础介绍

HAL库代码基础介绍 PWM预分频值与自动重装值ARR均要减1HAL_TIM_PWM_Start(htim2,TIM_CHANNEL_1);//设置占空比for(int i0;i100;i){_HAL_TIM_SET_COMPARE(htim2,TIM_CHANNEL_1,i);HAL_Delay(10);}for(int i0;i100;i){_HAL_TIM_SET_COMPARE(htim2,TIM_CHANNEL_1,100-i);HAL_Delay(10);}设置CCR的值_HAL_TIM_SET_COMPARE(htim2,TIM_CHANNEL_2,CCR值);//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////PWM中断比较中断当CNT等于CCR设定值就中断1.在NVIC Settings 中勾选 TIMx global interrupt2.启动中断的函数HAL_TIM_PWM_Start_IT(htimX, TIM_CHANNEL_Y)3.编写回调函数/* USER CODE BEGIN 4 */* param htim 定时器句柄指针void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim){// 1. 先判断是哪个定时器触发的例如TIM2if (htim-Instance TIM2){// 2. 判断是哪个通道例如通道2if (htim-Channel HAL_TIM_ACTIVE_CHANNEL_2){// 3.中断时真正想干的事}}}/* USER CODE END 4 */PWM更新中断CNT值等于自动重装值ARR值即周期值时归零瞬间触发中断1.在NVIC Settings 中勾选 TIMx global interrupt2.启动中断的函数HAL_TIM_Base_Start_IT(htimX) //与比较中断不一样3.编写回调函数/* USER CODE BEGIN 4 */void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){// 判断是哪个定时器if (htim-Instance TIM2){// 中断时真正想干的事}}/* USER CODE END 4 *////////////////////////////////////////////////////////////////捕获中断1.TIM的Slave Mode: Reset ModeTrigger Source : TI1FP1定时器通道的模式选为 “Input Capture direct mode”输入捕获直接模式。设置极性Rising Edge/ Falling Edge在 NVIC Settings 中勾选 TIMx global interrupt2.启动中断函数HAL_TIM_IC_Start_IT(htim2, TIM_CHANNEL_1);3.编写回调函数/* USER CODE BEGIN 4 */void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){// 1. 判断定时器if (htim-Instance TIM2){// 2. 判断通道如果只用1个通道可不加判断但建议加上if (htim-Channel HAL_TIM_ACTIVE_CHANNEL_1){// 3. 把刚锁存到CCR里的时间戳读取出来也就是外部信号跳变时的CNT值uint32_t capture HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1)1;// 4. 编写逻辑比如计算频率、切换边沿极性等freq fc/capture}}}/* USER CODE END 4 */PWMI模式在上面的基础上加一个通道设置为 Input Capture indirect modePolarity Selection : Falling Edge两个通道都启动HAL_TIM_IC_Start_IT(htim2, TIM_CHANNEL_1);HAL_TIM_IC_Start_IT(htim2, TIM_CHANNEL_2);int32_t frequint32_t dutyuint32_t capture/* USER CODE BEGIN 4 */void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){if (htim-Instance TIM2){//上升沿触发中断if (htim-Channel HAL_TIM_ACTIVE_CHANNEL_1){capture HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1)1;freq fc/capture}//下降沿触发中断{uint32_t capture2 HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2)1;duty capture2 *100/capture //*100是因为是百分比}}}/* USER CODE END 4 *///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////ADC//使用前校准放在初始化处HAL_ADCEx_Calibration_Start(hadc1);//开启ADCHAL_ADC_Start(hadc1);//等待转换HAL_ADC_PollForConversion(hadc1,HAL_MAX_DELAY);HAL_MAX_DELAY是等待的最大时间//获取结果int16_t value0;float voltage0.0;value HAL_ADC_GetValue(hadc1);voltage(float)value/4095.0*3.3;//显示小数的方法OLED_ShowNum(2,9,(uint32_t)voltage,1);//在2行9列显示一位整数OLED_ShowNum(2, 11,(uint16_t)voltage*100%100, 2);//在2行11列显示小数点后的两位ADC多通道//数组,用于存放ADC数据uint16_t values[4]{0};//放于while处for(uint8_t i0; i4;i){HAL_ADC_Start(hadc1);if(HAL_ADC_PollForConversion(hadc1,HAL_MAX_DELAY)HAL_OK){values[i]HAL_ADC_GetValue(hadc1);}}//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////DMA配置步骤启用DMA时钟、初始化DMA通道、配置源地址和目的地址、设置传输方向和数据大小、配置传输模式循环/正常、设置优先级、启用DMA中断看是否需要、启用DMA通道//初始化uint8_t DataA[]{0x01,0x02,0x03,0x04};uint8_t DataB[]{0,0,0,0};//启动DMAHAL_DMA_Starthdma_memtomem_dma1_channel1,(uint32_t*)DataA,(uint32_t*)DataB,4;通道、源地址、目标地址//等待传输完成HAL_DMA_PollForTransfer(hdma_memtomem_dma1_channel1,HAL_DMA_FULL_TRANSFER,HAL_MAX_DELAY);HAL_MAX_DELAY是设置的最长等待时间//等待传输完成HAL_DMA_PollForTransferhdma_memtomem_dma1_channel1,HAL_DMA_FULL_TRANSFER,HAL_MAX_DELAY);循环模式时//初始化uint8_t DataA[]{0x01,0x02,0x03,0x04};uint8_t DataB[]{0,0,0,0};hdma_memtomem_dma1_channel1.init.ModeDMA_CIRCULAR;HAL_DMA_Init(hdma_memtomem_dma1_channel1);HAL_DMA_Starthdma_memtomem_dma1_channel1,(uint32_t*)DataA,(uint32_t*)DataB,4;4代表要传输的数据单元个数///////////////////////////////////////////////////////////////DMA多通道ADC方法1在CODE BEGIN0中void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){if (hadchadc1){//ADC转换完成时想执行的操作OLED_ShowNum(1,1,value[0],5);}}while中HAL_ADC_Start_DMA(hadc1,(uint32_t*)values,4); 数据单元个数为4HAL_Delay1000);方法二ADC连续DMA循环设置ADC Continuous Conversion Mode 为 Enabled设置DMA Mode为CircularHAL_ADC_Start_DMA(hadc1,(uint32_t*)values,4);//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////USARTMode为Asynchronous发送HAL_UART_Transmit(huart1byteNumber,1,HAL_MAX_DELAY);(句柄要发送的数据地址要发送的字节数最大延迟时间)该函数发送成功会返回一个值HAL_OK 表示发送成功HAL_BUSY 表示正常发送数据无法立即发送HAL_TIMEOUT 表示发送超时HAL_ERROR 表示发生错误接受在PV处uint8_t receiveData[5];在while处HAL_UART_Receive(huart1,receiveData,5,HAL_MAX_DELAY);receiveData是接收数据的数组USART中断模式在nvic中打开usart的中断在begin中HAL_UART_Receive_IT(huart1,receiveData,sizeof(receiveData)); //接收启动中断的函数添加中断函数void HAL_USART_RxCpltCallback{HAL_UART_Transmit_IT(huart1,receiveData,sizeof(receiveData));HAL_UART_Receive_IT(huart1,receiveData,sizeof(receiveData)); //重新开始中断}//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////IIC///////////////////////////////////////////////////////////////软件IIC//引脚配置#define W_SCL(x) HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,x)#define W_SDA(x) HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,x)//引脚初始化void MyI2C_Init(void){MX_GPIO_Init();W_SCL(1);W_SDA(1);}uint8_t MyI2C_R_SDA (void){uint8_t BitValue;BitValue HAL_GPIO_ReadPin( GPIOB, GPIO_PIN_11);return BitValue ;}void MyI2C_Start(void){W_SDA(1);W_SCL(1);W_SDA(0);W_SCL(0);}void MyI2C_Stop(void){W_SDA(0);W_SCL(1);W_SDA(1);}void MyI2C_SendByte(uint8_t Byte){uint8_t i;for ( i 0; i 8; i){W_SDA(!!( Byte (0x80 i)));W_SCL(1);W_SCL(0);}W_SCL(1); //额外的一个时钟不处理应答信号W_SCL(0);}uint8_t MyI2C_ReceiveByte(void){uint8_t i, Byte 0x00 W_SDA(1);for ( i 0; i 8; i){W_SCL(1);if (MyI2C_R_SDA()){Byte | (0x80 i);}W_SCL(0);}return Byte}void OLED_WriteCommand(uint8_t Command){OLED_I2C_Start();OLED_I2C_SendByte(0x78); //从机地址OLED_I2C_SendByte(0x00); //写命令OLED_I2C_SendByte(Command);OLED_I2C_Stop();}uint8_t MyI2C_ReceiveAck(void){uint8_t AckBit W_SDA(1);W_SCL(1);AckBit MyI2C_R _SDA();W_SCL(0);return AckBit;}///////////////////////////////////////////////////////////////硬件IIC对于有内部寄存器的设备HAL_I2C_Mem_Write(hi2c1, 设备地址目标寄存器地址寄存器地址长度比如1代表1字节要写入的数据值数据字节长度超时时间);HAL_I2C_Mem_Read(hi2c1, 设备地址寄存器起始地址寄存器地址长度比如1代表1字节存放读取数据的数组读取的字节数超时时间);对于没有内部寄存器通过命令字节或者纯数据流的设备用 HAL_I2C_Master_Transmit 和 HAL_I2C_Master_Receive//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////SPI软件SPIPA4: CS PA5:CLK PA6:MISO PA7:MOSIvoid MySPI_W_SS(uint8_t BitValue){HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, BitValue);}void MySPI_W_SCK(uint8_t BitValue){HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, BitValue);}void MySPI_W_MOSI(uint8_t BitValue){HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, BitValue);}uint8_t MySPI_R_MISO(void){return HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6);}void MySPI_Init(void){MX_GPIO_Init(); //4引脚初始默认高电平其余5和7为低电平 457为推挽输出6为浮空输入或上拉输入MySPI_W_SS(1);MySPI_W_SCK(0);}void MySPI_Start(void){MySPI_W_SS(0);}void MySPI_Stop(void){MySPI_W_SS(1);}//使用SPI模式0来交换传输一个字节void MySPI_SwapByte(uint8_t ByteSend){uint8_t i , ByteReceive 0x00 ;for ( i 0; i 8; i){MySPI_W_MOSI(!!(ByteSend (0x80 i)));MySPI_W_SCK(1);if (MySPI_R_MISO()) {ByteReceive | (0x80 i) ; }MySPI_W_SCK(0);}return ByteReceive;}///////////////////////////////////////////////////////////////硬件SPIHAL_SPI_Transmit(hspi1, cmd, 1,1000); (句柄命令字节等待时间)HAL_SPI_Transmit(hspi1, response, 1,1000); (句柄数组名数组字节数等待时间)void WriteEnable(void){CS_LOW();HAL_SPI_Transmit(hspi1,WRITE_ENABLE, 1, 1000 );CS_HIGH();}//等待忙void WaitBusy(void){uint32_t Timeout 100000;uint8_t status;CS_LOW();HAL_SPI_Transmit(hspi1, READ_STATUS_REGISTER_1, 1,1000);HAL_SPI_Transmit(hspi1, status, 1,1000);while ((status 0x01) 0x01) //表示正在忙{Timeout --;if(Timeout 0){break; //等待超时}}HAL_SPI_Transmit(hspi1,WRITE_ENABLE, 1, 1000 );CS_HIGH();}//页编程void PageProgram(uint32_t Address, uint8_t *DataArray, uint16_t Count){uint8_t cmd[4] { PAGE_PROGRAM, (uint8_t)((Address 16) 0xFF),(uint8_t)((Address 8 ) 0xFF),(uint8_t)(Address 0xFF)} ;WriteEnable();CS_LOW();HAL_SPI_Transmit(hspi1,cmd, 4, 1000 );HAL_SPI_Transmit(hspi1,DataArray, Count, 1000 );CS_HIGH();WaitBusy();}//读数据void ReadData(uint32_t Address, uint8_t *DataArray, uint16_t Count){uint8_t cmd[4] { READ_DATA, (uint8_t)((Address 16) 0xFF),(uint8_t)((Address 8 ) 0xFF),(uint8_t)(Address 0xFF)} ;CS_LOW();HAL_SPI_Transmit(hspi1,cmd, 4, 1000 );HAL_SPI_Receive(hspi1,DataArray, Count, 1000 );CS_HIGH();}