STM32CubeMX-STM32F101- FreeRTOS

1、打开 STM32CubeMX -> New Project  -> MCU Selector -> STM32F101RBTx

2、选择 FREERTOS 系统

3、选择 RCC 高速时钟   PD0 和 PD1

 4、选择 SYS TIM4 作为基础时钟 , SWD(PA13 和PA14  )

DEBUG 选择 Serial Wire 为St-link SWD 调试管脚,可以不选 ,上电默认就是调试管脚;

注意 :Timebase Source 为啥要选TIM4 而不是Systick,因为FREERTOS 要使用Systick 作为调度时钟

5、选择 USART1 异步串口  PA9 和PA10

6、选择 LED1  和 LED2 GPIO模式, PA0 和 PA1

 7、时钟网络 clock configuration  配置 成最高36M时钟

8、配置  usart1 

 

 打开 usart 中断

 

添加 usart1 接收 和发送 DMA通道

9 、配置 FREERTOS

添加 3 个任务 LED1Task、LED2Task、Usart1Task,其他配置不变

10、点击生成代码,要求先设置工程

MDK 环境选择 keil 5

勾选 generate peripheral **** .c/.h **** 选项,保证 不同模块单独文件;

11 、打开工程 

在 gpio.c 中添加 2函数 操作LED 灯

/* USER CODE BEGIN 2 */

void Led1_op(int val)
{
    if (val)
    {
        HAL_GPIO_WritePin(GPIOA, LED1_Pin, GPIO_PIN_SET);
    }
    else
    {
        HAL_GPIO_WritePin(GPIOA, LED1_Pin, GPIO_PIN_RESET);
    }
}

void Led2_op(int val)
{
    if (val)
    {
        HAL_GPIO_WritePin(GPIOA, LED2_Pin, GPIO_PIN_SET);
    }
    else
    {
        HAL_GPIO_WritePin(GPIOA, LED2_Pin, GPIO_PIN_RESET);
    }
}
/* USER CODE END 2 */

在  freertos.c 中 修改 

/* StartLED1Task function */
void StartLED1Task(void const * argument)
{
  /* USER CODE BEGIN StartLED1Task */
  int flag = 0;
  /* Infinite loop */
  for(;;)
  {
    Led1_op(flag);
    flag = !flag;
    osDelay(500); // 500ms 交替
  }
  /* USER CODE END StartLED1Task */
}

/* StartLED2Task function */
void StartLED2Task(void const * argument)
{
  /* USER CODE BEGIN StartLED2Task */
  int flag = 0;
  /* Infinite loop */
  for(;;)
  {
    Led2_op(flag);
    flag = !flag;
    osDelay(1000); // 1000ms 交替
  }
  /* USER CODE END StartLED2Task */
}

接下来修改 串口dma 收发,在 usart.h 中添加 结构

/* USER CODE BEGIN Private defines */

#define RECEIVELEN          1024
#define USART_DMA_SENDING   1   //发送未完成
#define USART_DMA_SENDOVER  0   //发送完成
typedef struct
{
    uint8_t receive_flag:1;//空闲接收标记
    uint8_t dmaSend_flag:1;//发送完成标记
    uint16_t rx_len;//接收长度
    uint8_t usartDMA_rxBuf[RECEIVELEN];//DMA接收缓存
}USART_RECEIVETYPE;

extern USART_RECEIVETYPE UsartType1;
 


/* USER CODE END Private defines */

在 usart.c 中添加

/* USER CODE BEGIN 1 */
#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
 set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
	
PUTCHAR_PROTOTYPE
{
	HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
	return ch;
}
 
//DMA发送函数
void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length)
{
	while(UsartType1.dmaSend_flag == USART_DMA_SENDING);
	UsartType1.dmaSend_flag = USART_DMA_SENDING;
	HAL_UART_Transmit_DMA(&huart1, pdata, Length);
}
 
//DMA发送完成中断回调函数
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	 __HAL_DMA_DISABLE(huart->hdmatx);
	UsartType1.dmaSend_flag = USART_DMA_SENDOVER;
}
 
//串口接收空闲中断
void UsartReceive_IDLE(UART_HandleTypeDef *huart)
{
	uint32_t temp;
 
	if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))
	{ 
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);
		HAL_UART_DMAStop(&huart1);
		temp = huart1.hdmarx->Instance->CNDTR;
		UsartType1.rx_len =  RECEIVELEN - temp; 
		UsartType1.receive_flag=1;
		HAL_UART_Receive_DMA(&huart1,UsartType1.usartDMA_rxBuf,RECEIVELEN);
	}
}

/* USER CODE END 1 */

在 dma.c 中注释掉 

//HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 5, 0);
  //HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);

dma 接收中断关闭,不需要接收中断,本程序使用串口空闲中断读取dma数据;

在 mian.c ,mian 函数中添加

 /* USER CODE BEGIN 2 */
    HAL_UART_Receive_DMA(&huart1, UsartType1.usartDMA_rxBuf, RECEIVELEN);
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
  /* USER CODE END 2 */

使能串口 dma接收和空闲中断

在 freertos.c 中,修改

/* StartUsart1Task function */
void StartUsart1Task(void const * argument)
{
  /* USER CODE BEGIN StartUsart1Task */
  /* Infinite loop */
    for(;;)
    {
		if(UsartType1.receive_flag)//如果产生了空闲中断
        {
			UsartType1.receive_flag=0;//清零标记
			Usart1SendData_DMA(UsartType1.usartDMA_rxBuf,UsartType1.rx_len);//串口打印收到的数据。
		}
 		
    }
  /* USER CODE END StartUsart1Task */
}

实现串口接收到的内容回送。

编译加载 ,运行 ok !

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值