stm32ccu6基于HAl库的开发

目录

硬件情况:

pwm:

代码使用方式:

模式一:

模式二:

感谢声明:

硬件情况:

淘宝上面20几块绿色盗版开发板(支持正版),st_linkV2烧录器

 

 然后是导师的要求:
我们已经买了这个板,准备用它做一个直流电机控制的电路
我们用1个光电门检测旋转的起始点,另外1个光电门检测旋转位置。
基本要求有:
1、检测到起始点后输出另一个光电门的脉冲,用1个门电路控制脉冲是否输出;
2、检测到起始点后按规定的时序输出脉冲;
3、能和上位机通信,工作模式由上位机定。也可以通过引脚的电平组合定工作模式。

目标方案:
采用F401CCU6系统板,控制输出。PWM脉冲输出速度,工作模式上位机通信确定。

具体方案:按键a(KEY2B0)确定模式1,2:串口输出   "模式X"  ,
按下按键b(KEY3B1):串口输出(模式一)“请输入设定个数和设定输出PWM组(为了方便连续实验)”OR(模式二)“请输入设定t/T,输入循环次数”
在按一次按键a:
(模式一)开始检测光电门PWM,当稳定时,串口输出“开始工作”,检测脉冲单片机计脉冲数至设定个数,输出设定PWM(控制光电门输入脉冲,是个数组,最多可存储10个)
(模式二)开始检测光电门PWM,当稳定时,串口输出“开始工作,当前T:XXX”,检测到宽脉冲,计1,输出1.单片机计数至设定个数。输出0;

前前后后反正中途变方案了好多;

下面是干货,各种模块

用stm32ccu6开发板的人知道,像这种,资料很少,不向正点原子那种官方例程搞好,然后ctrl+c+v,so easy.它只有一个虚拟串口+定时灯+GPIO口的例程,一些F4库他还会删删减减,更为要命的是,有些同学(比如我)只会keil,不会说stmcubex(是真的强,狗头狗头),移植程序就很难。

但是主要在于三个程序:

pwm串口捕获,输出指定pwm,虚拟串口收发指令并控制(上位机还没有做好QAQ)

pwm输出:

开始输出。正点原子官方HAl例程直接整。

pwm串口捕获:

检测最终版:鬼才知道我修了几版。个式bug。

主要是主要就是声明一个接口,声明一个timer定时器,声明一个中断,clock切换,开始输出。,然后在main.c,设定数值,设定检测流程。

/* USER CODE BEGIN Header */
/**

  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2019 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "rtc.h"
#include "tim.h"
#include "usb_device.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usbd_cdc_if.h"
#include <stdio.h>

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
/* Buffers used for displaying Time and Date */
uint8_t aShowTime[50] = {0};
uint8_t aShowDate[50] = {0};
uint32_t capture_Buf[3] = {0};   //存放计数值
    uint8_t capture_Cnt = 0;    //状态标志位
    uint32_t high_time;   //高电平时间
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */



/**
  * @brief  Display the current time and date.
  * @param  showtime : pointer to buffer
  * @param  showdate : pointer to buffer
  * @retval None
  */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
	
	uint32_t tick,tick1,tick2;
	uint16_t uhAdc[2];
	uint8_t sendAdct[50];
//	float Vrefint,TempSensor;
	uint16_t Gpio = GPIO_PIN_All,GpioA = GPIO_PIN_All,GpioB = GPIO_PIN_All;
	CLEAR_BIT(GpioA,GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_8);//
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_RTC_Init();
  MX_USB_DEVICE_Init();
  MX_ADC1_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
  HAL_ADC_Start_DMA(&hadc1,(uint32_t *)uhAdc,sizeof(uhAdc));
  tick2 = tick1 = tick = HAL_GetTick();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  
	  switch (capture_Cnt){
	case 0:
		capture_Cnt++;
		__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
		HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);	//启动输入捕获       或者: __HAL_TIM_ENABLE(&htim5);
		break;
	case 3:
		high_time = capture_Buf[1]- capture_Buf[0];    //高电平时间
		//HAL_UART_Transmit(&htim2, (uint8_t *)high_time, 1, 0xffff);   //发送高电平时间
	  
		 CDC_Transmit_FS(sendAdct,sprintf((char *)sendAdct,"high_time: %ld \r\n",high_time));		
	   
	   
		//HAL_Delay(1000);   //延时1S
		capture_Cnt = 0;  //清空标志位
		break;
				
	}

	  
	  
	   /* D1 闪烁测试 */
	 /*if((HAL_GetTick() - tick >= 500 ))
	  {
		  tick = HAL_GetTick();
		  HAL_GPIO_TogglePin(LED_C13_GPIO_Port,LED_C13_Pin);
	  }*/
	 

	  
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

  /**Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
  /**Initializes the CPU, AHB and APB busses clocks
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /**Initializes the CPU, AHB and APB busses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
  PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_LSE, RCC_MCODIV_5);
}

/* USER CODE BEGIN 4 */

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	
	if(TIM2 == htim->Instance)
	{
		switch(capture_Cnt){
			case 1:
				capture_Buf[0] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//获取当前的捕获值.
				__HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);  //设置为下降沿捕获
				capture_Cnt++;
				break;
			case 2:
				capture_Buf[1] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//获取当前的捕获值.
				HAL_TIM_IC_Stop_IT(&htim2,TIM_CHANNEL_1); //停止捕获   或者: __HAL_TIM_DISABLE(&htim5);
				capture_Cnt++;    
		}
	
	}
	
}



/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

操作全在

可以下载stmcubex,也可以学到其他操作,实心推荐
Z小旋【STM32】HAL库 STM32CubeMX系列学习教程

虚拟串口收发指令并控制:

有一说一这部分有点久远了,先对借鉴的作者说一声感谢!!

主要是stmccu6这例程,本身就有CDC_XXX,这样的输出

另外为了进行控制

     if(my_RxLength!=0)
				{
				for(i=0;i<my_RxLength;i++)
				{
				//HAL_Delay(500u);
				
					//设定个数设定
						if(my_RxBuf[i]==97)//当输入串口a时+1
					{
					shedinggeshu=shedinggeshu+1;
					CDC_Transmit_FS(sendAdct,sprintf((char *)sendAdct,"\r\n  the set number: %d\r\n",shedinggeshu));
					}
					
						if(my_RxBuf[i]==98)//当输入串口b时-1
					{
					shedinggeshu=shedinggeshu-1;
					if(shedinggeshu==-1)
						{shedinggeshu=0;
						CDC_Transmit_FS(sendAdct,sprintf((char *)sendAdct,"\r\n  the set number Error%d\r\n"));}
					CDC_Transmit_FS(sendAdct,sprintf((char *)sendAdct,"\r\n  the set number: %d\r\n",shedinggeshu));
					}
					//设定输出PWM组
							if(my_RxBuf[i]==99)//当输入串口c时确定输入一个PWM
					{
					pwmnum=pwmnum+1;
					CDC_Transmit_FS(sendAdct,sprintf((char *)sendAdct,"\r\n  the set pwmnum: %d  ge\r\n",pwmnum));
					pwmflag=1;
					}
					if(pwmflag==1)
					
				{
					if(my_RxBuf[i]==97)//当输入串口a时+10
					{
					pwmcount=pwmcount+10;
					CDC_Transmit_FS(sendAdct,sprintf((char *)sendAdct,"\r\n  the set number: %d\r\n",pwmcount));
					}
					
						if(my_RxBuf[i]==98)//当输入串口b时-10
					{
					pwmcount=pwmcount-10;
					if(pwmcount<0)
						{pwmcount=0;
						CDC_Transmit_FS(sendAdct,sprintf((char *)sendAdct,"\r\n  the set number Error%d\r\n"));}
					CDC_Transmit_FS(sendAdct,sprintf((char *)sendAdct,"\r\n  the set number: %d\r\n",pwmcount));
					}
								if(my_RxBuf[i]==101)//当输入串口e时+1
					{
					pwmcount=pwmcount+1;
					CDC_Transmit_FS(sendAdct,sprintf((char *)sendAdct,"\r\n  the set number: %d\r\n",pwmcount));
					}
					
								if(my_RxBuf[i]==102)//当输入串口f时-1
					{
					pwmcount=pwmcount-1;
					if(pwmcount<0)
						{pwmcount=0;
						CDC_Transmit_FS(sendAdct,sprintf((char *)sendAdct,"\r\n  the set number Error%d\r\n"));}
					CDC_Transmit_FS(sendAdct,sprintf((char *)sendAdct,"\r\n  the set number: %d\r\n",pwmcount));
					}
								if(my_RxBuf[i]==100)//当输入串口d时停止修改PWM,pwmcount放置pwm100倍
					{
					pwmflag=0;
					//pwmzu[pwmnum-1]=pwmcount;	
					CDC_Transmit_FS(sendAdct,sprintf((char *)sendAdct,"\r\n  the end set pwmnum: %d  ge\r\n",pwmnum));
					CDC_Transmit_FS(sendAdct,sprintf((char *)sendAdct,"\r\n  the set number: %d\r\n",pwmcount));
					}
					
				}

					}
				for(i=0;i<my_RxLength;i++)
				{	
					my_RxBuf[i]=0;
				}
	
			
			}

就是把串口读取到的存储在一个数组,要用时挨个取出,为了之后不出错,还要即时清空。

cdc串口输出就有一点迷,会警告,总程序共有十个警告,但不影响使用。

代码分享:链接: https://pan.baidu.com/s/1p1gYMzV5YHxDJ5X8HghZhg?pwd=qhif 提取码: qhif 复制这段内容后打开百度网盘手机App,操作更方便哦 
--来自百度网盘超级会员v4的分享

希望能进行探讨在代码过程中发现什么问题。也希望能发表一下自身见解。

代码使用方式:

用flagmode来区分工作,

先进入flagmode==1:判断进入哪种工作模式,模式一串口输入“q”,模式二串口输入“p”,

模式一:

进入flagmode==5:输入工作数据,workliza,worklizb来判断模式几,然后我们是模式一,需要检测到特定脉冲,而我们则是用高电平时长检测,检测至设定个数,输出设定PWM波,所以一个整数,一个数组。输入一次“a”,设定个数+1;输入一次“b”,设定个数-1;输入一次“c”,设定数组值+1;且输入一次“g”,设定个数+10;输入一次“h”,设定个数-10;输入一次“e”,设定个数+1;输入一次“f”,设定个数-1;输入串口“d“时停止修改PWM,pwmcount放置pwm100倍。设定好一切之后,按一次”r“;

进入flagmode==2:按下”p“,输出当前高电平时间,再按下”s“,进入工作。

进入flagmode==4:串口输出“开始工作,当前T:XXX”,检测到宽脉冲,计1,输出1.单片机计数至设定个数。输出0;

会有一个回退程序:按下”r“,进行回退到flagmode==1;

模式二:

进入flagmode==5:输入工作数据,workliza,worklizb来判断模式几,然后我们是模式二,就是检测到一个指定信号脉冲,开始启动,知道当前高脉冲时间,然后不断输出一个时间比值上为1+t/T的脉冲,和检测次数。所以一个数组,一个整数。;输入一次“c”,设定数组值+1;且输入一次“g”,设定个数+10;输入一次“h”,设定个数-10;输入一次“e”,设定个数+1;输入一次“f”,设定个数-1;当输入串口d时停止修改zhouqibizhicount,zhouqibizhicount放置t/T倍。输入一次“a”,设定个数+1;输入一次“b”,设定个数-1设定好一切之后,按一次”r“;

进入flagmode==2:按下”q“,进入工作。

进入flagmode==4:然后会输出当前周期”T,按下”y,会自动输出当前高电平时间,输出pWM。检测到设定个数,停止

会有一个回退程序:按下”r“,进行回退到flagmode==1;

感谢声明:

感谢csdn作者:strongerhuang,(f4教程很棒,给了我极多的启发)

感谢正点原子官方(例程提供非常全面)

感谢csdn作者:Z小旋(输入捕获借鉴)

感谢csdn作者:21世纪不靠谱艺术表演家(虚拟串口教程非常完善)

猜你喜欢

转载自blog.csdn.net/prouue/article/details/127087149