目录
硬件情况:
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)
开始输出。正点原子官方HAl例程直接整。
检测最终版:鬼才知道我修了几版。个式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
/* 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****/
操作全在
有一说一这部分有点久远了,先对借鉴的作者说一声感谢!!
主要是stmccu6这例程,本身就有CDC_XXX,这样的输出
另外为了进行控制
if(my_RxLength!=0)
{
for(i=0;i
就是把串口读取到的存储在一个数组,要用时挨个取出,为了之后不出错,还要即时清空。
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世纪不靠谱艺术表演家(虚拟串口教程非常完善)