STM32 串口DMA接收 Openmv / K210 整数、小数字符串数据 (基于HAL库)

目录

  • 前言
  • 一、工程配置
  • 二、串口DMA部分代码
    • 1.源文件UART_DMA.c
    • 2.头文件UART_DMA.h
    • 3.stm32f1xx_it.c的修改
    • 4.串口收发DMA测试
  • 三、字符串数字提取代码
    • 1.源文件NumAndStr.c:
    • 2.头文件NumAndStr.h:
    • 3.测试:
  • 四、Openmv / K210 发送、STM32接收测试
  • 总结
  • 修订版本
    • UART_DMA.c
    • UART_DMA.h

平台: STM32 Cube IDE


前言

许多科创比赛中经常会有其他设备与STM32串口通讯的需求,比如可能需要Openmv / K210向STM32串口发送坐标的情况。下面我将介绍一种基于HAL库的串口DMA不定长数据收发和数据解读的方案。


一、工程配置

1.选择好芯片、配置好时钟和debug模式后,使能要用到的串口。
在这里插入图片描述
2.使能该串口的收发收发DMA:
在这里插入图片描述
3.使能串口全局中断,并生成工程文件。在这里插入图片描述

二、串口DMA部分代码

本部分代码修改自xia0816大佬写的《真正实现了STM32 HAL串口不定长数据的接收发送功能(DMA方式,不用限定单次接收长度和添加结束标志)》

1.源文件UART_DMA.c

#include "UART_DMA.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>uint8_t RxBuffer[UART_RX_BUF_SIZE] = {0};
uint8_t TxBuffer[UART_RX_BUF_SIZE] = {0};
uint8_t sendCompleteSign = 1;
uint8_t TxLen = 0;void DataProcess(void)
{//在这里加入数据处理的函数}//到USARTx_IRQHandler中添加,如:
//void USART1_IRQHandler(void)
//{
//  /* USER CODE BEGIN USART1_IRQn 0 */
//  if(__HAL_UART_GET_FLAG(&USB_Huart,UART_FLAG_IDLE))
//  {
//	  HAL_UART_IdleCallback(&USB_Huart);
//  }
//
//  /* USER CODE END USART1_IRQn 0 */
//  HAL_UART_IRQHandler(&huartx);
//}
void HAL_UART_IdleCallback(UART_HandleTypeDef *huart)
{__HAL_UART_CLEAR_IDLEFLAG(huart);{HAL_UART_DMAStop(huart);ProcessData();StartUartRxDMA();}
}void ProcessData()
{uint32_t len = 0;//得到已经接收了多少个字节 = 总共要接收的字节数 - ?NDTR F1为CNDTR F4为NDTR#ifdef __STM32F1xx_HAL_Hlen = UART_RX_BUF_SIZE - USB_Huart.hdmarx->Instance->CNDTR;#define ProcessDataOK#endif#ifdef  __STM32F4xx_HAL_Hlen = UART_RX_BUF_SIZE - USB_Huart.hdmarx->Instance->NDTR;#define ProcessDataOK#endif#ifndef ProcessDataOK增加所用芯片的版本#endifif(len > 0){if(sendCompleteSign == 1){
#if UART_RXTX_Switchmemset((void *)TxBuffer, 0, sizeof(TxBuffer));memcpy(TxBuffer, RxBuffer, len);TxLen = len;StartUartTxDMA();	//串口回显
#endif{//在这里面加入数据处理的函数DataProcess();}}}
}void USB_DMA_printf(const char *format,...)
{uint32_t length;va_list args;va_start(args, format);length = vsnprintf((char*)TxBuffer, sizeof(TxBuffer)+1, (char*)format, args);va_end(args);HAL_UART_Transmit_DMA(&USB_Huart,TxBuffer,length);
}void USB_printf(const char *format,...)
{uint32_t length;va_list args;va_start(args, format);length = vsnprintf((char*)TxBuffer, sizeof(TxBuffer)+1, (char*)format, args);va_end(args);HAL_UART_Transmit(&USB_Huart,TxBuffer,length,0xFFFF);
}/*** @brief  Tx Transfer completed callbacks.* @param  huart  Pointer to a UART_HandleTypeDef structure that contains*                the configuration information for the specified UART module.* @retval None*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{/* Prevent unused argument(s) compilation warning */
//  UNUSED(huart);if(huart == &USB_Huart){sendCompleteSign = 1;}/* NOTE: This function should not be modified, when the callback is needed,the HAL_UART_TxCpltCallback could be implemented in the user file*/
}/*** @brief  Rx Transfer completed callbacks.* @param  huart  Pointer to a UART_HandleTypeDef structure that contains*                the configuration information for the specified UART module.* @retval None*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{/* Prevent unused argument(s) compilation warning */
//  UNUSED(huart);if(huart == &USB_Huart){ProcessData();StartUartRxDMA();}/* NOTE: This function should not be modified, when the callback is needed,the HAL_UART_RxCpltCallback could be implemented in the user file*/
}uint8_t UartTxData(UART_HandleTypeDef *huart, uint8_t *buf, const uint32_t len)
{HAL_StatusTypeDef status;uint8_t ret = 1;if(sendCompleteSign == 0 || len == 0){return 0;}sendCompleteSign = 0;status = HAL_UART_Transmit_DMA(huart, (uint8_t*)buf, len);if(HAL_OK != status){ret = 0;}return ret;
}//启动DMA发送
uint8_t StartUartTxDMA()
{return UartTxData(&USB_Huart, TxBuffer, TxLen);
}uint8_t UartRxData(UART_HandleTypeDef *huart, uint8_t *buf, const uint32_t len)
{HAL_StatusTypeDef status;uint8_t ret = 1;status = HAL_UART_Receive_DMA(huart, (uint8_t*)buf, len);if(HAL_OK != status){ret = 0;}else{/* 开启空闲接收中断 */__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);}return ret;
}//启动DMA接收
uint8_t StartUartRxDMA()
{return UartRxData(&USB_Huart, RxBuffer, UART_RX_BUF_SIZE);
}

void ProcessData()中可能需要视所用芯片情况作部分修改,目前只测试过STM32F103VET6和STM32F411CEU6

    //得到已经接收了多少个字节 = 总共要接收的字节数 - ?NDTR F1为CNDTR F4为NDTR#ifdef __STM32F1xx_HAL_Hlen = UART_RX_BUF_SIZE - USB_Huart.hdmarx->Instance->CNDTR;#define ProcessDataOK#endif#ifdef  __STM32F4xx_HAL_Hlen = UART_RX_BUF_SIZE - USB_Huart.hdmarx->Instance->NDTR;#define ProcessDataOK#endif#ifndef ProcessDataOK增加所用芯片的版本#endif

2.头文件UART_DMA.h

#ifndef UART_DMA_UART_DMA_H_
#define UART_DMA_UART_DMA_H_#include "main.h"extern UART_HandleTypeDef huart1;	//修改为所用串口
#define USB_Huart huart1			//修改为所用串口#define UART_RX_BUF_SIZE 128#define UART_RXTX_Switch 1			//串口回显开关/*
要在Cube中开串口全局中断和收发DMA*/extern uint8_t RxBuffer[UART_RX_BUF_SIZE];
extern uint8_t TxBuffer[UART_RX_BUF_SIZE];
extern uint8_t TxLen;void USB_DMA_printf(const char *format,...);			//printf DMA方式
void USB_printf(const char *format,...);				//printf 普通方式
uint8_t UartTxData(UART_HandleTypeDef *huart, uint8_t *buf, const uint32_t len);
uint8_t StartUartRxDMA();								//接收DMA初始化
uint8_t StartUartTxDMA();								//不需要自己调用
void ProcessData();										//在里面添加数据处理函数
void HAL_UART_IdleCallback(UART_HandleTypeDef *huart);	//到USARTx_IRQHandler中添加#endif /* UART_DMA_UART_DMA_H_ */

3.stm32f1xx_it.c的修改

需要到stm32f1xx_it.c中的USARTx_IRQHandler添加几句话

//...
/* USER CODE BEGIN Includes */
#include "../UART_DMA/UART_DMA.h"
/* USER CODE END Includes */
//...
//...
/*** @brief This function handles USART1 global interrupt.*/
void USART1_IRQHandler(void)
{/* USER CODE BEGIN USART1_IRQn 0 */if(__HAL_UART_GET_FLAG(&USB_Huart,UART_FLAG_IDLE)){HAL_UART_IdleCallback(&USB_Huart);}/* USER CODE END USART1_IRQn 0 */HAL_UART_IRQHandler(&huart1);/* USER CODE BEGIN USART1_IRQn 1 *//* USER CODE END USART1_IRQn 1 */
}
//...

4.串口收发DMA测试

(2022年1月25日补充)新版Cube MX有BUG,生成的初始化代码顺序有问题,见STM32 HAL串口DMA发送一直失败 —— 攻城狮_鲨鱼,故建议在生成的初始化代码前手动

  MX_DMA_Init();MX_USART1_UART_Init();


在这里插入图片描述

启动串口DMA接收

//.../* USER CODE BEGIN 2 */StartUartRxDMA();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
//...

进入debug跑起来,将接收区缓存RxBuffer加入 现场表达式

//...uint8_t RxBuffer[UART_RX_BUF_SIZE] = {0};uint8_t TxBuffer[UART_RX_BUF_SIZE] = {0};uint8_t sendCompleteSign = 1;uint8_t TxLen = 0;
//...

在这里插入图片描述
在ProcessData()中的该处打上断点。
在这里插入图片描述
打开串口调试助手,选择好参数后发送一段测试字符串,可以发现该字符串已成功存入缓冲区。
在这里插入图片描述
随后又成功将数据通过DMA回显
在这里插入图片描述
至此串口DMA收发已成功实现。

而源文件中附有的USB_DMA_printf()和USB_printf()分别为DMA方式的printf和普通的printf

void USB_DMA_printf(const char *format,...)
{uint32_t length;va_list args;va_start(args, format);length = vsnprintf((char*)TxBuffer, sizeof(TxBuffer)+1, (char*)format, args);va_end(args);HAL_UART_Transmit_DMA(&USB_Huart,TxBuffer,length);
}void USB_printf(const char *format,...)
{uint32_t length;va_list args;va_start(args, format);length = vsnprintf((char*)TxBuffer, sizeof(TxBuffer)+1, (char*)format, args);va_end(args);HAL_UART_Transmit(&USB_Huart,TxBuffer,length,0xFFFF);
}

效果如下:
在这里插入图片描述
为了进一步处理数据,下面介绍字符串数字提取的方案。

三、字符串数字提取代码

改进型代码见C语言字符串数字提取函数,支持负数、浮点数、科学记数法
实测double数据直接传参数据会出错,故采取了指针的方式。

1.源文件NumAndStr.c:

/** NumAndStr.c**  Created on: Mar 15, 2021*      Author: 乙酸氧铍*/
#include "../NumAndStr/NumAndStr.h"
#include  <stdlib.h>int32_t str2int(uint8_t * str, uint8_t flag, uint8_t no)
{uint8_t No = 1;uint8_t * Str = str;uint8_t NumTemp[TempIntLen];while(No!=no){if(*Str == flag)No++;Str++;}No = 0;while(*Str != flag && *Str != '\r' && *Str != '\n' && *Str != '\0' && No < (TempIntLen - 1)){NumTemp[No] = *Str;Str++;No++;}NumTemp[No] = '\0';return atoi(NumTemp);
}void str2double(uint8_t * str, uint8_t flag, uint8_t no, double * Output)
{uint8_t No = 1;uint8_t * Str = str;uint8_t NumTemp[TempDoubleLen];uint8_t NumTemp_int[TempDoubleLen];double OutputNum;while(No!=no){if(*Str == flag)No++;Str++;}No = 0;while(*Str != flag && *Str != '\r' && *Str != '\n' && *Str != '\0' && No < (TempDoubleLen - 1)){NumTemp[No] = *Str;Str++;No++;}NumTemp[No] = '\0';NumTemp[(TempDoubleLen - 1)] = 0;No = 0;while(NumTemp[NumTemp[(TempDoubleLen - 1)]] != '\0' && NumTemp[(TempDoubleLen - 1)] < (TempDoubleLen - 1)){if(NumTemp[NumTemp[(TempDoubleLen - 1)]] == '.'){NumTemp[(TempDoubleLen - 1)]++;NumTemp_int[(TempDoubleLen - 1)] = NumTemp[(TempDoubleLen - 1)];}NumTemp_int[No] = NumTemp[NumTemp[(TempDoubleLen - 1)]];No++;NumTemp[(TempDoubleLen - 1)]++;}NumTemp_int[No]='\0';NumTemp[(TempDoubleLen - 1)] = NumTemp_int[(TempDoubleLen - 1)]++;OutputNum = (double)atoi(NumTemp_int);while(NumTemp[NumTemp[(TempDoubleLen - 1)]] != '\0'){OutputNum /= 10;NumTemp[(TempDoubleLen - 1)] ++;}*Output = OutputNum;
}

2.头文件NumAndStr.h:

/** NumAndStr.h**  Created on: Mar 15, 2021*      Author: 乙酸氧铍*/#ifndef NUMANDSTR_NUMANDSTR_H_
#define NUMANDSTR_NUMANDSTR_H_#include "main.h"#define TempDoubleLen 18
#define TempIntLen 11/*
str:数字字符串首地址
flag:分隔符
no:第no个数字 从1开始计
Output: 小数存放地址*/
extern int32_t str2int(uint8_t * str, uint8_t flag, uint8_t no);
extern void str2double(uint8_t * str, uint8_t flag, uint8_t no, double * Output);#endif /* NUMANDSTR_NUMANDSTR_H_ */

str:数字字符串首地址
flag:分隔符
no:第no个数字 从1开始计
Output: 小数存放地址

3.测试:

修改UART_DMA.c中的DataProcess()函数

#include "../NumAndStr/NumAndStr.h"		//包含头文件int32_t a,b,c;
double  d,e,f;
void DataProcess(void)
{//在这里加入数据处理的函数a = str2int(RxBuffer, ' ', 1);b = str2int(RxBuffer, ' ', 2);c = str2int(RxBuffer, ' ', 3);str2double(RxBuffer, ' ', 4, &d);str2double(RxBuffer, ' ', 5, &e);str2double(RxBuffer, ' ', 6, &f);
}

进入debug模式,监视变量a、b、c、d、e、f,使用串口调试助手再次发送一段测试字符串
效果如图所示:
在这里插入图片描述
可以看到六个数据都已成功存入对应的变量中,并成功回显。
在这里插入图片描述
且多次测试都能成功解读
在这里插入图片描述

四、Openmv / K210 发送、STM32接收测试

(示例) 平台: MaixPy IDE、K210 Maix Bit

K210 串口测试程序
延时500ms时

import utime
from board import board_info
from Maix import freq
from fpioa_manager import fm
from machine import UARTimport randomfm.register(9,fm.fpioa.UART1_TX)
fm.register(10,fm.fpioa.UART1_RX)
UART_USB = UART(UART.UART1, 115200, 8, None, 1, timeout = 1000, read_buf_len = 128)while(True):Tube_X = random.randint(-200,200)Tube_Y = random.randint(-200,200)Tube_Angle = random.random()print('%d %d %f'%(Tube_X, Tube_Y, Tube_Angle))UART_USB.write('%d %d %f\r\n'%(Tube_X, Tube_Y, Tube_Angle))utime.sleep_ms(500)

修改UART_DMA.c中的DataProcess()函数

int32_t Tube_X = 0, Tube_Y = 0;
double  Tube_Angle = 0;
void DataProcess(void)
{//在这里加入数据处理的函数Tube_X = str2int(RxBuffer, ' ', 1);Tube_Y = str2int(RxBuffer, ' ', 2);str2double(RxBuffer, ' ', 3, &Tube_Angle);
}

进入debug,如图所示,数据提取成功
在这里插入图片描述
延时15ms时

#...
while(True):Tube_X = random.randint(-200,200)Tube_Y = random.randint(-200,200)Tube_Angle = random.random()print('%d %d %f'%(Tube_X, Tube_Y, Tube_Angle))UART_USB.write('%d %d %f\r\n'%(Tube_X, Tube_Y, Tube_Angle))utime.sleep_ms(15)#...

在这里插入图片描述

总结

本文介绍了一种STM32 串口DMA收发并解读的方案,对CPU要求较小,只需自己选择分隔符号,不需要设计复杂的通信协议就能得到对应位置的数据,应该可以应用到使用STM32的多种科创比赛项目中去。

修订版本

UART_DMA.c

/** UART_DMA.c**  Created on: Mar 14, 2021*      Author: Royic*/
#include "UART_DMA.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>uint8_t RxBuffer[UART_RX_BUF_SIZE] = {0};
uint8_t TxBuffer[UART_RX_BUF_SIZE] = {0};
uint8_t sendCompleteSign = 1;
uint8_t TxLen = 0;
uint8_t USE_UART_DMA = 0;void DataProcess(UART_HandleTypeDef *huart, uint32_t Len)
{//在这里加入数据处理的函数
#ifdef USB_Huart_1if(huart == &USB_Huart_1){;}
#endif
#ifdef USB_Huart_2if(huart == &USB_Huart_2){;}
#endif
}//到USARTx_IRQHandler中添加,如:
//void USART1_IRQHandler(void)
//{
//  /* USER CODE BEGIN USART1_IRQn 0 */
//  if(__HAL_UART_GET_FLAG(&USB_Huart_1,UART_FLAG_IDLE))
//  {
//	  HAL_UART_IdleCallback(&USB_Huart_1);
//  }
//
//  /* USER CODE END USART1_IRQn 0 */
//  HAL_UART_IRQHandler(&huartx);
//}
void HAL_UART_IdleCallback(UART_HandleTypeDef *huart)
{__HAL_UART_CLEAR_IDLEFLAG(huart);{HAL_UART_DMAStop(huart);ProcessData(huart);StartUartRxDMA(huart);}
}void ProcessData(UART_HandleTypeDef *huart)
{uint32_t len = 0;len = UART_RX_BUF_SIZE - __HAL_DMA_GET_COUNTER(huart->hdmarx);if(len > 0){if(sendCompleteSign == 1){
#if UART_RXTX_Switchmemset((void *)TxBuffer, 0, sizeof(TxBuffer));memcpy(TxBuffer, RxBuffer, len);TxLen = len;StartUartTxDMA(huart);	//串口回显
#endif}{//在这里面加入数据处理的函数DataProcess(huart, len);}}
}void USB_DMA_printf(UART_HandleTypeDef *huart, const char *format,...)
{uint32_t length;va_list args;va_start(args, format);length = vsnprintf((char*)TxBuffer, sizeof(TxBuffer)+1, (char*)format, args);va_end(args);HAL_UART_Transmit_DMA(huart,TxBuffer,length);
}void USB_printf(UART_HandleTypeDef *huart, const char *format,...)
{uint32_t length;va_list args;va_start(args, format);length = vsnprintf((char*)TxBuffer, sizeof(TxBuffer)+1, (char*)format, args);va_end(args);HAL_UART_Transmit(huart,TxBuffer,length,0xFFFF);
}/*** @brief  Tx Transfer completed callbacks.* @param  huart  Pointer to a UART_HandleTypeDef structure that contains*                the configuration information for the specified UART module.* @retval None*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{/* Prevent unused argument(s) compilation warning */sendCompleteSign = 1;/* NOTE: This function should not be modified, when the callback is needed,the HAL_UART_TxCpltCallback could be implemented in the user file*/
}/*** @brief  Rx Transfer completed callbacks.* @param  huart  Pointer to a UART_HandleTypeDef structure that contains*                the configuration information for the specified UART module.* @retval None*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{/* Prevent unused argument(s) compilation warning */ProcessData(huart);StartUartRxDMA(huart);/* NOTE: This function should not be modified, when the callback is needed,the HAL_UART_RxCpltCallback could be implemented in the user file*/
}uint8_t UartTxData(UART_HandleTypeDef *huart, uint8_t *buf, const uint32_t len)
{HAL_StatusTypeDef status;uint8_t ret = 1;if(sendCompleteSign == 0 || len == 0){return 0;}sendCompleteSign = 0;status = HAL_UART_Transmit_DMA(huart, (uint8_t*)buf, len);if(HAL_OK != status){ret = 0;}return ret;
}//启动DMA发送
uint8_t StartUartTxDMA(UART_HandleTypeDef *huart)
{return UartTxData(huart, TxBuffer, TxLen);
}uint8_t UartRxData(UART_HandleTypeDef *huart, uint8_t *buf, const uint32_t len)
{HAL_StatusTypeDef status;uint8_t ret = 1;status = HAL_UART_Receive_DMA(huart, (uint8_t*)buf, len);if(HAL_OK != status){ret = 0;}else{/* 开启空闲接收中断 */__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);}return ret;
}//启动DMA接收
uint8_t StartUartRxDMA(UART_HandleTypeDef *huart)
{USE_UART_DMA = 1;return UartRxData(huart, RxBuffer, UART_RX_BUF_SIZE);
}

UART_DMA.h

/** UART_DMA.h**  Created on: Mar 14, 2021*      Author: Royic*/#ifndef UART_DMA_UART_DMA_H_
#define UART_DMA_UART_DMA_H_#include "main.h"#define USB_Huart_1 huart1			//修改为所用串口
extern UART_HandleTypeDef USB_Huart_1;#define USB_Huart_2 huart2			//修改为所用串口
extern UART_HandleTypeDef USB_Huart_2;#define UART_RX_BUF_SIZE 128#define UART_RXTX_Switch 0			//串口回显开关
//#define UART_DMA_Switch 0			/*
要在Cube中开串口全局中断和收发DMA*/extern uint8_t RxBuffer[UART_RX_BUF_SIZE];
extern uint8_t TxBuffer[UART_RX_BUF_SIZE];
extern uint8_t TxLen;
extern uint8_t USE_UART_DMA;void USB_DMA_printf(UART_HandleTypeDef *huart, const char *format,...);			//printf DMA方式
void USB_printf(UART_HandleTypeDef *huart, const char *format,...);				//printf 普通方式
uint8_t UartTxData(UART_HandleTypeDef *huart, uint8_t *buf, const uint32_t len);
uint8_t StartUartRxDMA(UART_HandleTypeDef *huart);								//接收DMA初始化
uint8_t StartUartTxDMA(UART_HandleTypeDef *huart);								//不需要自己调用
void ProcessData(UART_HandleTypeDef *huart);										//在里面添加数据处理函数
void HAL_UART_IdleCallback(UART_HandleTypeDef *huart);	//到USARTx_IRQHandler中添加#endif /* UART_DMA_UART_DMA_H_ */

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400870.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

6000字|22张图 带你彻底弄懂Zookeeper分布式锁

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

【HDU2896】病毒侵袭——ac自动机

网上很多代码都略显繁琐&#xff0c;看了一下yy dalao的代码感觉很好&#xff0c;但他懒得打题解&#xff08;好吧我也是 以0为根节点的话&#xff0c;我把yy的一段代码删了改用fail[c]x0?0:ch[fail[x]][i];来实现特判&#xff0c;效果还不错&#xff01;也算是AC自动机的模版…

经典 HTML5 Javascript 俄罗斯方块游戏

Blockrain.js 是一个使用 HTML5 & JavaScript 开发的经典俄罗斯方块游戏。只需要复制和粘贴一段代码就可以玩起来了。最重要的是&#xff0c;它是响应式的&#xff0c;无论你的显示屏多么宽都能自动匹配。你可以自定义你想要的颜色以适应您的网站&#xff0c;也可以调整方块…

【电赛PID半天入门】从接触编码器到调出好康的PID波形

从接触编码器到调出好康的PID波形认识电机及编码器只需动动手指&#xff0c;就能让STM32得到电机转过的角度让电机转起来认识PID控制①比例调节器②积分调节③微分调节④比例积分微分调节数字PID调节器&#xff08;1&#xff09;数字PID位置型控制算法&#xff08;2&#xff09…

算法的复杂度分析

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

PHP面向对象 封装与继承

知识点&#xff1a; PHP封装三个关键词&#xff1a; 一、public 公有的&#xff0c;被public修饰的属性和方法&#xff0c;对象可以任意访问和调用 二、private 私有的&#xff0c;被private修饰的属性和方法&#xff0c;只能在类内部的方法可以进行调用&#xff0c;或者被子类…

POJ 1380 坐标旋转

题意&#xff1a; 问第二个矩形能不能放进第一个矩形中。 题解&#xff1a; 暴力旋转第二个矩形&#xff0c;判断左右、上下是否同时小于第一个矩形 当然&#xff0c;数学推导也可以&#xff0c;挺简单的相似神马的胡搞就行~ View Code 1 #include <iostream>2 #include…

MSP430F5529 DriverLib 库函数学习笔记(一)时钟配置和闪烁LED

目录一、新建工程二、时钟树时钟系统结构时钟系统的原理时钟树配置实战三、点灯工程师封装好的初始化函数平台&#xff1a;Code Composer Studio 10.3.1 MSP430F5529 LaunchPad™ Development Kit (MSP‑EXP430F5529LP) 一、新建工程 二、时钟树 时钟系统结构 &#xff08;1&…

libcurl上传文件

libcurl参数很多&#xff0c;一不小心就容易遇到问题。曾经就遇到过一个很蛋疼的问题&#xff1a;libcurl断点下载>> 这里主要汇总一下&#xff0c;libcurl上传的二种方式&#xff1a; 1、直接上传文件&#xff0c;类似form表单<input type”file” />&#xff0c;…

MSP430F5529 DriverLib 库函数学习笔记(二)GPIO

目录硬知识一、MSP430单片机端口概述二、通用IO端口输出特性三、端口P1和P21&#xff0e;输入寄存器PxIN2&#xff0e;输出寄存器PxOUT3&#xff0e;方向寄存器PxDIR4&#xff0e;上拉/下拉电阻使能寄存器PxREN5&#xff0e;输出驱动能力调节寄存器PxDS6&#xff0e;功能选择寄…

MSP430F5529 DriverLib 库函数学习笔记(三)认识中断

目录一、硬知识中断的基本概念MSP430单片机中断源中断响应过程中断返回过程中断嵌套二、msp430f5529.h中所列的中断向量宏定义平台&#xff1a;Code Composer Studio 10.3.1 MSP430F5529 LaunchPad™ Development Kit (MSP‑EXP430F5529LP) 一、硬知识 中断的基本概念 中断…

推荐系统相关算法

摘要&#xff1a; 热门推荐 协同过滤算法 矩阵分解 基于内容的推荐&#xff08;文本&#xff0c;标签&#xff0c;特征/profile&#xff09; 基于图的算法 内容&#xff1a; 热门推荐&#xff1a; 热门推荐本质上是一个排行榜&#xff0c;可能会考虑到时间衰减&#xff0c;商品…

冒泡排序的简单理解

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

司机和售票员问题 信号signal注册一例

#include <stdio.h> #include <stdlib.h> #include <signal.h>pid_t pid;void driver_handler(int signo) //司机的信号处理函数 {if (signo SIGUSR1)printf("Lets go!\n");if (signo SIGUSR2)printf("Stop the bus!\n");if (signo …

MSP430F5529 DriverLib 库函数学习笔记(四)UART通信

目录硬知识USCI通信模块USCI的UART模式1. USCI初始化和复位2. 异步通信字符格式3. 异步多机通信模式4. 自动波特率检测5. IrDA编码和解码6. 自动错误检测7. USCI接收使能8. USCI发送使能9. UART波特率的产生10. UART波特率的设置&#xff08;重要&#xff09;&#xff08;1&…

MSP430F5529 DriverLib 库函数学习笔记(四点五)printf打印输出

目录代码实现使相应工程支持打印浮点数实验结果平台&#xff1a;Code Composer Studio 10.3.1 MSP430F5529 LaunchPad™ Development Kit (MSP‑EXP430F5529LP)代码实现 重定向fputc(int ch, FILE *f)直接使用printf的方法只有字符串和%s打印正常&#xff0c;数字打印不出来…

flag

mark, to remember

MSP430F5529 DriverLib 库函数学习笔记(五)定时器A

目录硬知识定时器A 16位定时器原理&#xff08;1&#xff09;时钟源选择和分频器&#xff08;2&#xff09;Timer_A工作模式&#xff08;3&#xff09;捕获/比较模块&#xff08;4&#xff09;Timer_A中断&#xff08;重要&#xff09;定时器A API (机翻)定时器A配置和控制的函…

vim 常用快捷键(整理版)

最常用&#xff1a; x 删除后面的字符 X 删除前一个字符 删除3个字符就是3x dd:删除一行 D 删除到行尾 J:删除换行符&#xff0c;使下一行并上来。 nJ:连接后面的n行 u:撤销上一次操作 U:撤销当前行的所有修改 ctrlr:对撤消的撤消 I 在行首插入 a 在光标后插入 A…

MSP430F5529 DriverLib 库函数学习笔记(六)定时器A产生PWM波

目录1.通过Timer_A_outputPWM配置产生PWM波初始化函数计算修改占空比的函数整体程序效果2.单定时器产生多路PWM信号初始化函数实验结果3.对称PWM信号的产生初始化程序实验结果平台&#xff1a;Code Composer Studio 10.3.1 MSP430F5529 LaunchPad™ Development Kit (MSP‑EX…