stm32笔记[5]-FreeRTOS及(软IIC)读写AT24C02

STM32CubeIDE使用FreeRTOS教程资料

FreeRTOS 从入门到精通1--实时操作系统的前世今生
FreeRTOS 从入门到精通2--人生若只如初见,初识STM32CubeIDE
FreeRTOS 从入门到精通3--千呼万唤始出来,你好世界
FreeRTOS 从入门到精通4--堆栈管理知多少
FreeRTOS 从入门到精通5--任务管理这件事(上)
FreeRTOS 从入门到精通6--任务管理这件事(下)(对比PLC,安卓)
FreeRTOS 从入门到精通7--队列管理,天涯若比邻
FreeRTOS 从入门到精通8--但见时光流似箭,岂知天道曲如弓,软件定时器之应用
FreeRTOS 从入门到精通9--探讨中断管理
FreeRTOS 从入门到精通10--资源管理(互斥量与信号量)
FreeRTOS从入门到精通·实战篇1 - 任务调度

STM32CubeIDE已经把FreeRTOS深度整合到了自家的系统中去了,所以移植FreeRTOS变得非常方便。在项目文件里有个ioc文件,ioc文件是负责配置stm32参数的文件,FreeRTOS的设置就在那个文件里。如果你是新建项目的话,程序首先会自动跳到配置stm32芯片的画面中去并把最后的结果保存成ioc文件。

在interface中根据需求选择CMSIS_V1或者CMSIS_V2后便移植好了。你此时可以看到FreeRTOS前面有个绿色的勾,这个代表FreeRTOS已经设置好了。当设置好一切后点击保存按钮,系统便会自动生成代码。STM32CubeIDE帮助开发者节省了很多开发的时间,移植从此就成了点个鼠标的事。

CMSIS RTOS是ARM公司设计的对操作系统的一个抽象封装。它提供了一种标准化的API接口让开发者可以调用嵌入式操作系统的功能而不必理会底层到底采用的是哪种操作系统。举个通俗的例子,比如读者想尝试其它的操作系统如鸿蒙LiteOS等又害怕移植会很花精力,如果LiteOS支持CMSIS-RTOS接口的话,读者基本可以不做修改就可以直接运行了,因为CMSIS RTOS API接口会负责调用系统的相关功能。(当然目前STM32CubeIDE只有针对FreeRTOS的直接选项)

CMSIS RTOS v1是为基于Cortex-M内核的单片机设计的。CMSIS RTOS v2是CMSIS RTOS v1的扩展添加了对适用于Armv8-M内核和多核芯片的操作系统的支持.

CMSIS_RTOS对比FreeRTOS:

  1. 内核控制: osKernelStart->vTaskStartScheduler
  2. 线程控制: osThreadCreate->xTaskCreate
  3. Semaphore: osSemaphoreCreate->vSemaphoreCreateBinary或xSemaphoreCreateCounting
  4. Mutex: osMutexWait->xSemaphoreTake
  5. 消息队列: osMessagePut->xQueueSend或xQueueSendFromISR
  6. 定时器: osTimerCreate->xTimerCreate

FreeRTOS的任务优先级

[https://zhuanlan.zhihu.com/p/601864510]

用户配置任务的优先级数值越小,那么此任务的优先级越低,空闲任务的优先级是 0。

简单来说,FreeRTOS实时系统能够创建多个独立的任务,任务之间互不干扰。任务创建之后并不是一起运行的,而是通过优先级顺序进行任务的调用,和调度也没有依赖关系。所以不管什么时候程序只能执行一个任务,只有当该任务执行完成或者被打断才能执行下一个任务。具体应该执行那个任务是由调度器来进行负责,因此RTOS可以重复的启动和停止每个任务。这里RTOS调度器为了确保处理器在进行任务交换时的环境(寄存器、堆栈内容)与交换之后的任务是完全相同。 因此,为了这一点的实现,每个任务都应该有自己的堆栈空间。当任务进行切换,执行环境则保存到该任务的堆栈中,所以,当一段时间后切换回该任务,它能够精确地回复上次工作时的状态。

具有相同优先级的就绪状态任务将使用时间切片轮询调度方式共享可用的处理时间。

STM32读写AT24C02(软IIC)

[https://zhuanlan.zhihu.com/p/78546479]
AT24C02的读写命令:

位7 位6 位5 位4 位3 位2 位1 位0
1 0 1 0 A2 A1 A0 R/W标志

I2C的7位设备地址为1010 000,A2,A1,A0由硬件连接决定,如硬件原理图所示,E2、E1、E0都是接地,所以都为0。
当要向AT24C02写数据时,R/W位为0,则写地址为1010 0000,即是十六进制数:0xA0
当要向AT24C02读数据时,R/W位为1,则读地址为1010 0001,即是十六进制数:0xA1

A2, A1和A0引脚都是接地,芯片高四位统一为1010(十六进制为A)所以器件地址就是:1010 000X

字节写:
字节写操作首先发送设备地址字和写确认(也就是0XA0));在收到这个地址,EEPROM将响应一个“0”。
然后发送8位数据储存地址(在容量大于2K的芯片是word adress,也就是字地址,一个字为两个字节,所以一次是写两个字节地址,分别为要写入地址的高8位和低八位共16位地址);在收到两个8位数据字地址之后,EEPROM将再输出一个“0”响应。最后发送数据,发送结束后产生一个0的应答。
寻址设备,如微控制器,在收到这些操作后必须以停止条件终止写序列。此时EEPROM进入到非易失性存储器的内部定时写周期twp。在这个写周期中,所有输入都被禁用,直到写完成,EEPROM才会响应。

页写:
页写:1K/2K EEPROM能够进行8字节的页写,而4K、8K和16K设备能够进行16字节的页写。页写的初始化与字节写的初始化是一样的,但是微控制器不会在第一个数据字被写入后发送一个停止条件。相反,在EEPROM确认接收到第一个数据字后,微控制器可以发送最多服务器(1K/2K)或15个(4K、8K、16K)更多的数据字。EEPROM在收到每个数据字后将以一个“O”响应。微控制器必须使用停止条件终止页写序列(参见第10页上的图9)。数据字地址较低的三位(1K/2K)或四位(4K, 8K, 16K)位在收到每个数据字后内部递增。较高的数据字地址位不递增,保持内存页行位置。当内部生成的单词address到达页面边界时,下面的字节被放置在同一页面的开头。如果超过8个(1K/2K)或16个(4K, 8K, 16K)数据字被传输到EEPROM,数据字地址将“滚动”,之前的数据将被覆盖.

软IIC读写AT24C02

[http://news.eeworld.com.cn/mcu/ic550513.html]
写数据:

void AT24CXX_WriteOneByte(u8 WriteAddr,u8 DataToWrite){
	//I2CInit();	
	I2CStart();//产生IIC起始信号
	I2CSendByte(0XA0);//发送外设地址0XA0	
	I2CWaitAck();//等待应答
	I2CSendByte(WriteAddr);//发送储存地址
	I2CWaitAck(); 	 										  		   
	I2CSendByte(DataToWrite);//发送字节							   
	I2CWaitAck();  		    	   
	I2CStop();//产生停止信号
	HAL_Delay(10);//10ms
}

读数据:

u8 AT24CXX_ReadOneByte(u8 ReadAddr){
	//I2CInit();  
	u8 temp=0;//用于保存读取到的数据变量									 
  	I2CStart(); //产生一个起始信号
	//IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));   //发送器件地址0XA0,末位为0代表写数据 	 
	I2CSendByte(0xA0);//发送器件地址0XA0,末位为0代表写数据   
	I2CWaitAck();//产生一个应答信号
  	//IIC_Send_Byte(ReadAddr%256);   //发送低地址
	I2CSendByte(ReadAddr);//发送读地址
	I2CWaitAck();	                
	I2CStart();//再次产生一个起始信号
	I2CSendByte(0XA1);//发送器件地址,末位为1代表读数据进入接收模式			   
	I2CWaitAck();	 
  	temp=I2CReceiveByte(0);//接收数据   
  	I2CStop();//停止IIC	    
	return temp;
}

代码

i2c_hal.h

#ifndef __I2C_HAL_H
#define __I2C_HAL_H

#include "stm32g4xx_hal.h"

void I2CStart(void);
void I2CStop(void);
unsigned char I2CWaitAck(void);
void I2CSendAck(void);
void I2CSendNotAck(void);
void I2CSendByte(unsigned char cSendByte);
unsigned char I2CReceiveByte(void);
void I2CInit(void);

#endif

i2c_hal.c

#include "i2c_hal.h"

#define DELAY_TIME	20

/**
  * @brief SDA������ģʽ����
  * @param None
  * @retval None
  */
void SDA_Input_Mode()
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    GPIO_InitStructure.Pin = GPIO_PIN_7;
    GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
    GPIO_InitStructure.Pull = GPIO_PULLUP;
    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/**
  * @brief SDA�����ģʽ����
  * @param None
  * @retval None
  */
void SDA_Output_Mode()
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    GPIO_InitStructure.Pin = GPIO_PIN_7;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStructure.Pull = GPIO_NOPULL;
    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/**
  * @brief SDA�����һ��λ
  * @param val ���������
  * @retval None
  */
void SDA_Output( uint16_t val )
{
    if ( val )
    {
        GPIOB->BSRR |= GPIO_PIN_7;
    }
    else
    {
        GPIOB->BRR |= GPIO_PIN_7;
    }
}

/**
  * @brief SCL�����һ��λ
  * @param val ���������
  * @retval None
  */
void SCL_Output( uint16_t val )
{
    if ( val )
    {
        GPIOB->BSRR |= GPIO_PIN_6;
    }
    else
    {
        GPIOB->BRR |= GPIO_PIN_6;
    }
}

/**
  * @brief SDA����һλ
  * @param None
  * @retval GPIO����һλ
  */
uint8_t SDA_Input(void)
{
	if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) == GPIO_PIN_SET){
		return 1;
	}else{
		return 0;
	}
}


/**
  * @brief I2C�Ķ�����ʱ
  * @param None
  * @retval None
  */
static void delay1(unsigned int n)
{
    uint32_t i;
    for ( i = 0; i < n; ++i);
}

/**
  * @brief I2C��ʼ�ź�
  * @param None
  * @retval None
  */
void I2CStart(void)
{
    SDA_Output(1);
    delay1(DELAY_TIME);
    SCL_Output(1);
    delay1(DELAY_TIME);
    SDA_Output(0);
    delay1(DELAY_TIME);
    SCL_Output(0);
    delay1(DELAY_TIME);
}

/**
  * @brief I2C�����ź�
  * @param None
  * @retval None
  */
void I2CStop(void)
{
    SCL_Output(0);
    delay1(DELAY_TIME);
    SDA_Output(0);
    delay1(DELAY_TIME);
    SCL_Output(1);
    delay1(DELAY_TIME);
    SDA_Output(1);
    delay1(DELAY_TIME);

}

/**
  * @brief I2C�ȴ�ȷ���ź�
  * @param None
  * @retval None
  */
unsigned char I2CWaitAck(void)
{
    unsigned short cErrTime = 5;
    SDA_Input_Mode();
    delay1(DELAY_TIME);
    SCL_Output(1);
    delay1(DELAY_TIME);
    while(SDA_Input())
    {
        cErrTime--;
        delay1(DELAY_TIME);
        if (0 == cErrTime)
        {
            SDA_Output_Mode();
            I2CStop();
            return ERROR;
        }
    }
    SDA_Output_Mode();
    SCL_Output(0);
    delay1(DELAY_TIME);
    return SUCCESS;
}

/**
  * @brief I2C����ȷ���ź�
  * @param None
  * @retval None
  */
void I2CSendAck(void)
{
    SDA_Output(0);
    delay1(DELAY_TIME);
    delay1(DELAY_TIME);
    SCL_Output(1);
    delay1(DELAY_TIME);
    SCL_Output(0);
    delay1(DELAY_TIME);

}

/**
  * @brief I2C���ͷ�ȷ���ź�
  * @param None
  * @retval None
  */
void I2CSendNotAck(void)
{
    SDA_Output(1);
    delay1(DELAY_TIME);
    delay1(DELAY_TIME);
    SCL_Output(1);
    delay1(DELAY_TIME);
    SCL_Output(0);
    delay1(DELAY_TIME);

}

/**
  * @brief I2C����һ���ֽ�
  * @param cSendByte ��Ҫ���͵��ֽ�
  * @retval None
  */
void I2CSendByte(unsigned char cSendByte)
{
    unsigned char  i = 8;
    while (i--)
    {
        SCL_Output(0);
        delay1(DELAY_TIME);
        SDA_Output(cSendByte & 0x80);
        delay1(DELAY_TIME);
        cSendByte += cSendByte;
        delay1(DELAY_TIME);
        SCL_Output(1);
        delay1(DELAY_TIME);
    }
    SCL_Output(0);
    delay1(DELAY_TIME);
}

/**
  * @brief I2C����һ���ֽ�
  * @param None
  * @retval ���յ����ֽ�
  */
unsigned char I2CReceiveByte(void)
{
    unsigned char i = 8;
    unsigned char cR_Byte = 0;
    SDA_Input_Mode();
    while (i--)
    {
        cR_Byte += cR_Byte;
        SCL_Output(0);
        delay1(DELAY_TIME);
        delay1(DELAY_TIME);
        SCL_Output(1);
        delay1(DELAY_TIME);
        cR_Byte |=  SDA_Input();
    }
    SCL_Output(0);
    delay1(DELAY_TIME);
    SDA_Output_Mode();
    return cR_Byte;
}

//
void I2CInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    GPIO_InitStructure.Pin = GPIO_PIN_7 | GPIO_PIN_6;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Pull = GPIO_PULLUP;
    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
}

at24c02.h

#ifndef __AT24C02_H
#define __AT24C02_H
#include "main.h"
#include "i2c_hal.h"//软IIC

#ifndef u8
#define u8 uint8_t
#endif
#ifndef uint8_t
#define uint8_t unsigned char
#endif
/*
 * AT24C02 2kb = 2048bit = 2048/8 B = 256 B
 * 32 pages of 8 bytes each
 *
 * Device Address
 * 1 0 1 0 A2 A1 A0 R/W
 * 1 0 1 0 0  0  0  0 = 0XA0
 * 1 0 1 0 0  0  0  1 = 0XA1
 * 使用软IIC
 */
 //写地址
#define     AT24C02_WRITE_ADDRESS       0xA0
//读地址
#define     AT24C02_READ_ADDRESS        0xA1

//存储结构体(我们用来测试的)
typedef struct EEPROM_ST{
	uint8_t init_flag  ;
	uint8_t led_setting_status ;
	uint8_t buzzer_setting_status ;
}EEPROM_DATA;
extern EEPROM_DATA eerom_data ;

void Default_Setting(void);
//从AT24C02读取数据
//int AT24C02_Read(uint16_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead);
extern u8 AT24CXX_ReadOneByte(u8 ReadAddr);
//写数据到AT24C02
//int AT24C02_Write(uint16_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite);
extern void AT24CXX_WriteOneByte(u8 WriteAddr,u8 DataToWrite);
#endif //__AT24C02_H

at24c02.c

#include "at24C02.h"
void AT24CXX_WriteOneByte(u8 WriteAddr,u8 DataToWrite){
	//I2CInit();
	I2CStart();//产生IIC起始信号
	I2CSendByte(0XA0);//发送外设地址0XA0
	I2CWaitAck();//等待应答
	I2CSendByte(WriteAddr);//发送储存地址
	I2CWaitAck();
	I2CSendByte(DataToWrite);//发送字节
	I2CWaitAck();
	I2CStop();//产生停止信号
	HAL_Delay(10);//10ms
}
u8 AT24CXX_ReadOneByte(u8 ReadAddr){
	//I2CInit();
	u8 temp=0;//用于保存读取到的数据变量
  	I2CStart(); //产生一个起始信号
	//IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));   //发送器件地址0XA0,末位为0代表写数据
	I2CSendByte(0xA0);//发送器件地址0XA0,末位为0代表写数据
	I2CWaitAck();//产生一个应答信号
  	//IIC_Send_Byte(ReadAddr%256);   //发送低地址
	I2CSendByte(ReadAddr);//发送读地址
	I2CWaitAck();
	I2CStart();//再次产生一个起始信号
	I2CSendByte(0XA1);//发送器件地址,末位为1代表读数据进入接收模式
	I2CWaitAck();
  	temp=I2CReceiveByte();//接收数据
  	I2CStop();//停止IIC
	return temp;
}

main.c

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdlib.h"
#include "stdio.h"
#include "lcd.h"
#include "i2c_hal.h"
#include "stdarg.h"
#include "string.h"
#include "at24c02.h"


/* USER CODE END Includes */

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

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define TX_BUF_LEN 256
#define KEY_B1 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) //B1按键PB0
#define KEY_B2 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) //B2按键PB1
#define KEY_B3 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2) //B3按键PB2
#define KEY_B4 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) //B4按键PA0

#define KEY_B1_PRESS 1
#define KEY_B2_PRESS 2
#define KEY_B3_PRESS 3
#define KEY_B4_PRESS 4

#define DELAY_TIME 200//延时时间/ms

#ifndef u8
#define u8 uint8_t
#endif
#ifndef uint8_t
#define uint8_t unsigned char
#endif
/* USER CODE END PD */

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

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .priority = (osPriority_t) osPriorityNormal,
  .stack_size = 128 * 4
};
osThreadId_t TaskHandle_LED;
//LED任务配置
const osThreadAttr_t Task_LED_attributes = {
  .name = "LED",
  .priority = (osPriority_t) osPriorityHigh,//高优先级
  //.priority = (osPriority_t) osPriorityNormal,
  .stack_size = 128 * 4
};
u8 magic_number=0;//暂存24C02数据
/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);//系统时钟配置
static void MX_GPIO_Init(void);//GPIO端口配置
void StartDefaultTask(void *argument);//默认任务
void Task_LED(void *argument);//LED流水灯任务
void Display_PSD_view();//PSD密码输入界面
void Display_STA_view();//PWM输出状态界面
void LED_test(void);//测试LED
//void Read_and_Write();//测试读写
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
char chars_to_display[3]="@@@";//显示的三个密码//初始是@@@
char default_password[3]="123";//初始密码//默认密码123
char this_password[3]="123";//现在密码
u8 frequence_kHz=1;//默认1kHz频率
u8 duty_ratio=10;//占空比10%
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* 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();
  /* USER CODE BEGIN 2 */
  LCD_Init();//初始化LCD屏幕
  I2CInit();//初始化软件I2C
  {//测试
	  LED_test();//LED流水灯测试
  }
  /* USER CODE END 2 */

  /* Init scheduler */
  osKernelInitialize();//初始化任务调度器

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of defaultTask */
  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  //新建LED任务
  TaskHandle_LED = osThreadNew(Task_LED, NULL, &Task_LED_attributes);
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
  /* USER CODE END RTOS_EVENTS */

  /* Start scheduler */
  osKernelStart();//启动任务调度器

  /* We should never get here as control is now taken by the scheduler */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
	  //pass
    /* 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};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
  RCC_OscInitStruct.PLL.PLLN = 20;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses 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_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0
                          |GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4
                          |GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8
                          |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5|GPIO_PIN_8|GPIO_PIN_9, GPIO_PIN_RESET);

  /*Configure GPIO pins : PC13 PC14 PC15 PC0
                           PC1 PC2 PC3 PC4
                           PC5 PC6 PC7 PC8
                           PC9 PC10 PC11 PC12 */
  GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0
                          |GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4
                          |GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8
                          |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : PA8 */
  GPIO_InitStruct.Pin = GPIO_PIN_8;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PB5 PB8 PB9 */
  GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_8|GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument){
  /* USER CODE BEGIN 5 */

  /* Infinite loop */
  for(;;){
    //osDelay(1);

	 {//调试
	 Display_PSD_view();//显示密码界面
	 osDelay(6000);//延时6s
	 }
  }
  /* USER CODE END 5 */
}
//添加的任务
/*
 * @功能:流水灯
 * //低电平有效
1. PC8 : LD1
2. PC9 : LD2
3. PC10 : LD3
4. PC11 : LD4
5. PC12 : LD5
6. PC13 : LD6
7. PC14 : LD7
8. PC15 : LD8
 */
void Task_LED(void *argument){
	 while(1){
		 //LD1
		 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_8);
		 //LE为高电平时,Dn输入端的数据进入锁存器
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
		 osDelay(200);//等待数据稳定
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
		 osDelay(1000);//延时1s
	     //LD2
	     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_9);
	     //LE为高电平时,Dn输入端的数据进入锁存器
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
		 osDelay(200);//等待数据稳定
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
		 osDelay(1000);//延时1s
	     //LD3
	     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_10);
	     //LE为高电平时,Dn输入端的数据进入锁存器
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
		 osDelay(1000);//延时1s
		 //LD4
		 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_11);
		 //LE为高电平时,Dn输入端的数据进入锁存器
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
		 osDelay(1000);//延时1s
		 //LD5
		 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_12);
		 //LE为高电平时,Dn输入端的数据进入锁存器
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
		 osDelay(1000);//延时1s
		 //LD6
		 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
		 //LE为高电平时,Dn输入端的数据进入锁存器
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
		 osDelay(1000);//延时1s
		 //LD7
		 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_14);
		 //LE为高电平时,Dn输入端的数据进入锁存器
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
		 osDelay(1000);//延时1s
		 //LD8
		 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_15);
		 //LE为高电平时,Dn输入端的数据进入锁存器
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
		 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
		 osDelay(1000);//延时1s
		 {//测试
		 Display_STA_view();//显示PWM界面
		 osDelay(2000);//延时2s
		 //LCD_SetBackColor(Yellow);//背景黄色
		 LCD_Clear(Yellow);
		 }
	    }
}
/*
 * @功能:显示PSD界面
 */
void Display_PSD_view(){
	//清屏
	LCD_Clear(Black);
	LCD_SetBackColor(Black);//背景黑色
	LCD_SetTextColor(White);//前景白色
	//显示标题PSD
	LCD_DisplayStringLine(Line1,(char *)"    PSD             ");//第二行,(1,5)
	char b1[30];
	char b2[30];
	char b3[30];
	sprintf(b1,"    B1:%c             ",chars_to_display[0]);
	LCD_DisplayStringLine(Line3,(char*)b1);//第四行,B1密码
	sprintf(b2,"    B2:%c             ",chars_to_display[1]);
	LCD_DisplayStringLine(Line4,(char*)b2);//第五行,B2密码
	sprintf(b3,"    B3:%c             ",chars_to_display[2]);
	LCD_DisplayStringLine(Line5,(char*)b3);//第六行,B3密码
	AT24CXX_WriteOneByte(0x00,2);//写入数据'2'
	magic_number=AT24CXX_ReadOneByte(0x00);//读取数据
	sprintf(b3,"magic_num:%d          ",magic_number);
	LCD_DisplayStringLine(Line6,(char*)b3);//第七行,显示魔法数字
	//PWM_1kHz();//PWM_1kHz输出
	//Scan_key();//按键扫描=>如果按键有变调用PSD_view刷新;
}
/*
 * @功能:显示STA界面
 */
void Display_STA_view(){
	//清屏
	LCD_Clear(Black);
	LCD_SetBackColor(Black);//背景黑色
	LCD_SetTextColor(White);//前景白色
	//显示标题STA
	LCD_DisplayStringLine(Line1,(char *)"    STA             ");//第二行,(1,5)
	char F[30];//频率
	char D[30];//占空比
	//u16 frequence_kHz=1;//频率kHz
	u16 frequence_Hz=1000*frequence_kHz;
	sprintf(F,"    F:%4dHz           ",frequence_Hz);
	LCD_DisplayStringLine(Line3,(char*)F);//第四行,频率
	u16 duty_ratio=1;//占空比
	sprintf(D,"    D:%2d%%           ",duty_ratio);
	LCD_DisplayStringLine(Line4,(char*)D);//第五行,占空比
	//PWM_2kHz();//PWM_2kHz输出
	//LED_ok();//LD1点亮5s后熄灭
	//HAL_Delay(5000);//延时5s
	//Display_PSD_view();//回到密码输入界面
}
/*
 * @功能:LED测试
 */
void LED_test(void){
	//循环5次
	int i=0;
	for(;i<5;i++){
		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
		HAL_Delay(DELAY_TIME);

		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
		HAL_Delay(DELAY_TIME);

		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
		HAL_Delay(DELAY_TIME);

		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
		HAL_Delay(DELAY_TIME);

		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
		HAL_Delay(DELAY_TIME);

		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
		HAL_Delay(DELAY_TIME);

		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
		HAL_Delay(DELAY_TIME);

		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
		HAL_Delay(DELAY_TIME);
	}
}
/**
  * @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 */
  __disable_irq();
  while (1)
  {
  }
  /* 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,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

效果

posted @ 2023-02-26 22:18  qsBye  阅读(907)  评论(0编辑  收藏  举报