STM32F1內部FLASH讀寫例程

1、環境

STM32F107RC核心板 + Atollic TrueStudio + Win8.1

2、STM32F1系列單片機分類

打開參考手冊第三章,可以獲知:不同儲存容量的單片機有不同的FLASH分佈,而主要分爲以下幾類。1、low-density,2、medium-density,3、high-density,4、connectivity line。我們需要根據使用的單片機容量,確認其FLASH分佈。

下圖中,Table 3是STM32F107RC規格書上的關於兼容性的描述。從這裏以及規格書上文描述,我們可以知道:

STM32F107RC屬於connectivity line。

 

 

 3、硬石STM32F1開源的源代碼

3.1 stm32f107_flash.c

/**
  ******************************************************************************
  * 文件名程: stm_flash.c 
  * 作    者: 硬石嵌入式開發團隊
  * 版    本: V1.0
  * 編寫日期: 2015-10-04
  * 功    能: 內部Falsh讀寫實現
  ******************************************************************************
  * 說明:
  * 本例程配套硬石stm32開發板YS-F1Pro使用。
  * 
  * 淘寶:
  * 論壇:http://www.ing10bbs.com
  * 版權歸硬石嵌入式開發團隊所有,請勿商用。
  ******************************************************************************
  */
/* 包含頭文件 ----------------------------------------------------------------*/
#include "stm32f107_flash.h"

/* 私有類型定義 --------------------------------------------------------------*/
/* 私有宏定義 ----------------------------------------------------------------*/
#if STM32_FLASH_SIZE < 256
  #define STM_SECTOR_SIZE  1024 //字節
#else 
  #define STM_SECTOR_SIZE	 2048
#endif


/* 私有變量 ------------------------------------------------------------------*/
#if STM32_FLASH_WREN	//如果使能了寫 
static uint16_t STMFLASH_BUF [ STM_SECTOR_SIZE / 2 ];//最多是2K字節
static FLASH_EraseInitTypeDef EraseInitStruct;
#endif

/* 擴展變量 ------------------------------------------------------------------*/
/* 私有函數原形 --------------------------------------------------------------*/
/* 函數體 --------------------------------------------------------------------*/
/**
  * 函數功能: 讀取指定地址的半字(16位數據)
  * 輸入參數: faddr:讀地址(此地址必須爲2的倍數!!)
  * 返 回 值: 返回值:對應數據.
  * 說    明:無
  */
uint16_t STMFLASH_ReadHalfWord ( uint32_t faddr )
{
	return *(__IO uint16_t*)faddr; 
}

#if STM32_FLASH_WREN	//如果使能了寫   
/**
  * 函數功能: 不檢查的寫入
  * 輸入參數: WriteAddr:起始地址
  *           pBuffer:數據指針
  *           NumToWrite:半字(16位)數
  * 返 回 值: 無
  * 說    明:無
  */
void STMFLASH_Write_NoCheck ( uint32_t WriteAddr, uint16_t * pBuffer, uint16_t NumToWrite )   
{ 			 		 
  uint16_t i;
	
  for(i=0;i<NumToWrite;i++)
  {
	HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,WriteAddr,pBuffer[i]);
	WriteAddr+=2;                                    //地址增加2.
  }
} 

/**
  * 函數功能: 從指定地址開始寫入指定長度的數據
  * 輸入參數: WriteAddr:起始地址(此地址必須爲2的倍數!!)
  *           pBuffer:數據指針
  *           NumToWrite:半字(16位)數(就是要寫入的16位數據的個數.)
  * 返 回 值: 無
  * 說    明:無
  */
void STMFLASH_Write ( uint32_t WriteAddr, uint16_t * pBuffer, uint16_t NumToWrite )	
{
  uint32_t SECTORError = 0;
  uint16_t secoff;	   //扇區內偏移地址(16位字計算)
  uint16_t secremain; //扇區內剩餘地址(16位字計算)
  uint16_t i;
  uint32_t secpos;	   //扇區地址
  uint32_t offaddr;   //去掉0X08000000後的地址
	
  if(WriteAddr<FLASH_BASE||(WriteAddr>=(FLASH_BASE+1024*STM32_FLASH_SIZE)))return;//非法地址
	
  HAL_FLASH_Unlock();						//解鎖
	
  offaddr=WriteAddr-FLASH_BASE;		//實際偏移地址.
  secpos=offaddr/STM_SECTOR_SIZE;			//扇區地址  0~127 for STM32F103RBT6
  secoff=(offaddr%STM_SECTOR_SIZE)/2;		//在扇區內的偏移(2個字節爲基本單位.)
  secremain=STM_SECTOR_SIZE/2-secoff;		//扇區剩餘空間大小
  if(NumToWrite<=secremain)secremain=NumToWrite;//不大於該扇區範圍
	
  while(1)
  {
	STMFLASH_Read(secpos*STM_SECTOR_SIZE+FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//讀出整個扇區的內容
	for(i=0;i<secremain;i++)//校驗數據
	{
	  if(STMFLASH_BUF[secoff+i]!=0XFFFF)break;//需要擦除
	}
	if(i<secremain)//需要擦除
	{
	  //擦除這個扇區
	  /* Fill EraseInit structure*/
      EraseInitStruct.TypeErase     = FLASH_TYPEERASE_PAGES;
      EraseInitStruct.PageAddress   = secpos*STM_SECTOR_SIZE+FLASH_BASE;
      EraseInitStruct.NbPages       = 1;
      HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError);

      for(i=0;i<secremain;i++)//複製
      {
    	STMFLASH_BUF[i+secoff]=pBuffer[i];
      }
      STMFLASH_Write_NoCheck(secpos*STM_SECTOR_SIZE+FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//寫入整個扇區
	}
    else
    {
      STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);//寫已經擦除了的,直接寫入扇區剩餘區間. 				   
    }
    if(NumToWrite==secremain)break;//寫入結束了
    else//寫入未結束
    {
      secpos++;				//扇區地址增1
      secoff=0;				//偏移位置爲0
      pBuffer+=secremain;  	//指針偏移
      WriteAddr+=secremain;	//寫地址偏移
      NumToWrite-=secremain;	//字節(16位)數遞減
      if(NumToWrite>(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2;//下一個扇區還是寫不完
      else secremain=NumToWrite;//下一個扇區可以寫完了
    }
  };
  HAL_FLASH_Lock();//上鎖
}



#endif

/**
  * 函數功能: 從指定地址開始讀出指定長度的數據
  * 輸入參數: ReadAddr:起始地址
  *           pBuffer:數據指針
  *           NumToRead:半字(16位)數
  * 返 回 值: 無
  * 說    明:無
  */
void STMFLASH_Read ( uint32_t ReadAddr, uint16_t *pBuffer, uint16_t NumToRead )   	
{
  uint16_t i;

  for(i=0;i<NumToRead;i++)
  {
	pBuffer[i]=STMFLASH_ReadHalfWord(ReadAddr);//讀取2個字節.
	ReadAddr+=2;//偏移2個字節.
  }
}

/*
 * 函數名:Buffercmp
 * 描述  :比較兩個緩衝區中的數據是否相等
 * 輸入  :-pBuffer1     src緩衝區指針
 *         -pBuffer2     dst緩衝區指針
 *         -BufferLength 緩衝區長度
 * 輸出  :無
 * 返回  :-PASSED pBuffer1 等於   pBuffer2
 *         -FAILED pBuffer1 不同於 pBuffer2
 */
TestStatus Buffercmp(uint16_t* pBuffer1, uint16_t* pBuffer2, uint16_t BufferLength)
{
  while(BufferLength--)
  {
    printf("data:%d - %d \n",*pBuffer1 , *pBuffer2);
    if(*pBuffer1 != *pBuffer2)
    {
      return FAILED;
    }

    pBuffer1++;
    pBuffer2++;
  }
  return PASSED;
}


/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式開發團隊 *****END OF FILE****/

3.2 stm32f107_flash.h

#ifndef __STMFLASH_H__
#define __STMFLASH_H__

/* 包含頭文件 ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"

/* 類型定義 ------------------------------------------------------------------*/
/* 宏定義 --------------------------------------------------------------------*/
/************************** STM32 內部 FLASH 配置 *****************************/
#define STM32_FLASH_SIZE        256  // 所選STM32的FLASH容量大小(單位爲K)
#define STM32_FLASH_WREN        1    // stm32芯片內容FLASH 寫入使能(0,禁用;1,使能)

typedef enum
{
  FAILED = 0,
  PASSED = !FAILED
}TestStatus;

#define  FLASH_WriteAddress     0x0803F800            // 寫在靠後位置,防止破壞程序
#define  FLASH_ReadAddress      FLASH_WriteAddress
#define  FLASH_TESTSIZE         512                 //實際是512*2=1024字節


/* 擴展變量 ------------------------------------------------------------------*/
/* 函數聲明 ------------------------------------------------------------------*/
uint16_t STMFLASH_ReadHalfWord(uint32_t faddr);		  //讀出半字

void STMFLASH_WriteLenByte(uint32_t WriteAddr, uint32_t DataToWrite, uint16_t Len );	      //指定地址開始寫入指定長度的數據
uint32_t STMFLASH_ReadLenByte(uint32_t ReadAddr, uint16_t Len );					                    	//指定地址開始讀取指定長度數據
void STMFLASH_Write( uint32_t WriteAddr, uint16_t * pBuffer, uint16_t NumToWrite );		//從指定地址開始寫入指定長度的數據
void STMFLASH_Read( uint32_t ReadAddr, uint16_t * pBuffer, uint16_t NumToRead );   	//從指定地址開始讀出指定長度的數據
//static TestStatus Buffercmp(uint16_t* pBuffer1, uint16_t* pBuffer2, uint16_t BufferLength);
TestStatus Buffercmp(uint16_t* pBuffer1, uint16_t* pBuffer2, uint16_t BufferLength);

#endif /* __STMFLASH_H__ */

/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式開發團隊 *****END OF FILE****/

3.3 main.c

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "can.h"
#include "dma.h"
#include "lwip.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "string.h"
#include "tcp_echoclient.h"

/* USER CODE END Includes */

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

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define COUNTOF(__BUFFER__)   (sizeof(__BUFFER__) / sizeof(*(__BUFFER__)))

/* USER CODE END PD */

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

/* USER CODE END PM */

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

/* USER CODE BEGIN PV */
uint32_t  counter_10ms, counter_50ms, counter_100ms, counter_200ms, counter_500ms, counter_1000ms, counter_2000ms, counter_5000ms, counter_10s;
uint8_t flag_1ms, flag_10ms, flag_50ms, flag_100ms, flag_200ms, flag_500ms, flag_1000ms, flag_2000ms, flag_5000ms, flag_10s;
uint8_t b_KeyNumber;

uint8_t a_DtuInBuffer[100];
uint16_t b_DtuInBufferRxCnt;

uint8_t a_DtuOutBuffer[100];
uint16_t b_DtuOutBufferRxCnt;

struct netif gnetif;
extern struct tcp_pcb *echoclient_pcb;
uint32_t status_TCPProc;


uint8_t a_SocketConfig[7];
uint8_t a_SocketHeartBeat[60];
uint8_t a_SocketHeartBeatInterval[2];
uint8_t a_SocketRegister[60];

uint8_t a_DtuInOutConfig[2];

uint8_t b_WifiMode;
uint8_t a_RouterSsid[20];
uint8_t a_RouterPswd[20];

uint8_t a_Rs485Config[5];
uint8_t a_CanConfig[5];

uint8_t flag_DtuConfigUpdate;
uint8_t flag_DtuEthReady = 0;

uint32_t b_HeartBeatPackageCnt = 0;

uint32_t b_232STM32ParamConfigBusyCnt = 0;	//嘗試通過串口和STM32交互時候,會讓出相應時間,優先處理

/* 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 */
void Task_HeartBeatPackSent(void)
{
  uint16_t b_interval;

  b_interval = (a_SocketHeartBeatInterval[0]<<8) + a_SocketHeartBeatInterval[1];

  b_HeartBeatPackageCnt++;
  if(b_HeartBeatPackageCnt>=b_interval)
  {
    b_HeartBeatPackageCnt = 0;


    if(a_DtuInOutConfig[1]==1)
    {
      if(flag_8266DTUReady==1)
      {
    	HAL_UART_Transmit(&huart3, a_SocketHeartBeat, strlen((char*)a_SocketHeartBeat), 100);
    	printf("\r\n");
    	printf("\r\nA heart beat package is sent.\r\n ");
      }
    }
    else if(a_DtuInOutConfig[1]==2)
    {
      if(status_TCPProc>=2)
      {
    	tcp_senddata(1);
    	printf("\r\n");
    	printf("\r\nA heart beat package is sent.\r\n ");
      }
    }
  }
}
void cleanDtuInBuffer(void)
{
  uint32_t i;
  for(i=0;i<b_DtuInBufferRxCnt;i++)
  {
	a_DtuInBuffer[i] = 0;
  }
  b_DtuInBufferRxCnt = 0;
}
void cleanDtuOutBuffer(void)
{
  uint32_t i;
  for(i=0;i<b_DtuOutBufferRxCnt;i++)
  {
	a_DtuOutBuffer[i] = 0;
  }
  b_DtuOutBufferRxCnt = 0;
}

void Task_DirectTransfer(void)
{
  uint32_t i, k;
  //把數據輸出到以太網或者WIFI
  if(a_DtuInOutConfig[1]==1)
  {
	if(flag_8266DTUReady==1)
	{
	  if(b_DtuInBufferRxCnt>0)
	  {
		printf("\r\n");
		printf("\r\nData sent to Wifi: ");
		HAL_UART_Transmit(&huart3, (uint8_t*)a_DtuInBuffer, b_DtuInBufferRxCnt, 100);
		HAL_UART_Transmit(&huart1, (uint8_t*)a_DtuInBuffer, b_DtuInBufferRxCnt, 100);	//debug
	    cleanDtuInBuffer();
	  }
	}
  }
  else if(a_DtuInOutConfig[1]==2)
  {
	if(status_TCPProc>=2)
	{
	  if(status_TCPProc == 2)
	  {
	    tcp_senddata(0);	//專門發送註冊包
	  }
	  if(b_DtuInBufferRxCnt>0)
	  {
		if(status_TCPProc <= 3)
		{
		  tcp_senddata(0);
		}
		else
		{
		  status_TCPProc = 0;
		}
		cleanDtuInBuffer();
	  }
	}
  }


  //把數據輸出到RS232,RS485或者CAN
  if(a_DtuInOutConfig[0]==1)
  {
	if(b_DtuOutBufferRxCnt>0)
	{
	  HAL_UART_Transmit(&huart1, (uint8_t*)a_DtuOutBuffer, b_DtuOutBufferRxCnt, 100);
	  cleanDtuOutBuffer();
	}
  }
  else if(a_DtuInOutConfig[0]==2)
  {
	if(b_DtuOutBufferRxCnt>0)
	{
	  printf("\r\n");
	  printf("\r\nData sent to RS485: ");
	  HAL_UART_Transmit(&huart1, (uint8_t*)a_DtuOutBuffer, b_DtuOutBufferRxCnt, 100);//debug
	  RS485_TX_MODE();
	  HAL_UART_Transmit(&huart5, (uint8_t*)a_DtuOutBuffer, b_DtuOutBufferRxCnt, 100);
	  HAL_Delay(1);
	  RS485_RX_MODE();
	  cleanDtuOutBuffer();
	}
  }
  else if(a_DtuInOutConfig[0]==3)
  {
	if(b_DtuOutBufferRxCnt>0)
	{
	  k = 0;
	  if(b_DtuOutBufferRxCnt>8)
	  {
		for(i=0; i<8; i++)
		{
		  Can_TxData[i] = a_DtuOutBuffer[i];
		  k += Can_TxData[i];
		}
	  }
	  else
	  {
		for(i=0; i<b_DtuOutBufferRxCnt; i++)
		{
		  Can_TxData[i] = a_DtuOutBuffer[i];
		  k += Can_TxData[i];
		}
	  }
	  if(k>0)
	  {
		if(b_DtuOutBufferRxCnt>8)
		{
		  Can_TxMessage(0, Can_TxHeader.StdId, 8, Can_TxData);
		}
		else
		{
		  Can_TxMessage(0, Can_TxHeader.StdId, b_DtuOutBufferRxCnt, Can_TxData);
		}
		ArrayLeftShift8bits(a_DtuOutBuffer, &b_DtuOutBufferRxCnt);
	  }
	  else
	  {
		b_DtuOutBufferRxCnt = 0;
	  }
	}
  }
}
void Task_DtuRedoConfig(void)
{
  if(flag_DtuConfigUpdate==0)
	  return;

  HAL_Delay(10);
  printf("Re-initialize ETH, WIFI module, RS485...  ");
  //ETH:
  if(status_TCPProc >= 2)
  {
	  tcp_echoclient_disconnect();
	  status_TCPProc = 0;
  }
  //ESP8266:
  if(Status_NodeMCU>=6)
  {
	  sprintf((char *)a_8266TxBuffer, "+++");		//esp8266 接收到這個+++會停止透傳模式
	  HAL_UART_Transmit(&huart3, (uint8_t *)a_8266TxBuffer, strlen((char *)a_8266TxBuffer), 100);
	  Status_NodeMCU = 0;
	  HAL_Delay(100);
  }
  //485
  //MX_RS485_Reconfigure();
  printf("Completed.\r\n");
  //
  flag_DtuConfigUpdate = 0;

  HAL_UART_Receive_IT(&huart1, &b_232RxByte, 1);
}
/* 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();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  MX_USART3_UART_Init();
  MX_CAN1_Init();
  MX_UART5_Init();
  MX_LWIP_Init();
  /* USER CODE BEGIN 2 */

  RS232Interact_Init();
  printf("Hello. STM32F107_DTU project: DTU. All in one.\n");

  HAL_UART_Receive_IT(&huart1, &b_232RxByte, 1);
  HAL_UART_Receive_IT(&huart5, &b_485RxByte, 1);


  sprintf((char *)a_8266TxBuffer, "+++");		//esp8266 接收到這個+++會停止透傳模式
  HAL_UART_Transmit(&huart3, (uint8_t *)a_8266TxBuffer, strlen((char *)a_8266TxBuffer), 100);
  Status_NodeMCU = 0;

  status_TCPProc = 0;

  RS485_RX_MODE();

  CAN_Config_User();


  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	if(a_DtuInOutConfig[1]==2)
	{
	  MX_LWIP_Process();
	}
	if(flag_1ms ==1)
	{
	  flag_1ms = 0;
	  Task_232PC_Interact();

	  if(flag_DtuConfigUpdate ==1)
	  {
		Task_DtuRedoConfig();
	  }
	  if(b_232STM32ParamConfigBusyCnt>6)
	  {
	    Task_DirectTransfer();
	  }
	}
	if(flag_10ms==1)
	{
	  flag_10ms=0;

	}
	if(flag_50ms==1)	{		flag_50ms=0;	    }
	if(flag_100ms==1)
	{
	  if(b_232STM32ParamConfigBusyCnt>6)
	  {
		if(a_DtuInOutConfig[1]==1)
		{
		  if((flag_ProcNodeMCUActive ==1)&&(status_232PC<12))
		  {
			Proc_NodeMCU();
		  }
		}
	  }
	  flag_100ms=0;
	}
	if(flag_200ms==1)	{		flag_200ms=0;	    }
	if(flag_500ms==1)	{		flag_500ms=0;		}
	if(flag_1000ms==1)
	{
	  flag_1000ms=0;
	  HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);

	  if(b_232STM32ParamConfigBusyCnt>6)
	  {
		if(a_DtuInOutConfig[1]==2)
		{
		  if(status_TCPProc<=1)
		  {
			printf("connecting to TCP Server...\r\n");
			tcp_echoclient_connect();
		  }
		}
		Task_HeartBeatPackSent();
	  }
	  if(flag_ProcNodeMCUActive ==0)
	  {
		flag_ProcNodeMCUActive = 1;
	  }
	  if(b_232STM32ParamConfigBusyCnt<80)
	  {
		b_232STM32ParamConfigBusyCnt++;
	  }
	}
	if(flag_2000ms==1)
	{
	  flag_2000ms=0;

	}
	if(flag_5000ms==1)
	{
	  flag_5000ms=0;
	}

	if(flag_10s==1)
	{
	  flag_10s=0;
	}
    /* 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};

  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV5;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.Prediv1Source = RCC_PREDIV1_SOURCE_PLL2;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  RCC_OscInitStruct.PLL2.PLL2State = RCC_PLL2_ON;
  RCC_OscInitStruct.PLL2.PLL2MUL = RCC_PLL2_MUL10;
  RCC_OscInitStruct.PLL2.HSEPrediv2Value = RCC_HSE_PREDIV2_DIV2;
  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();
  }
  /** Enables the Clock Security System 
  */
  HAL_RCC_EnableCSS();
  /** Configure the Systick interrupt time 
  */
  __HAL_RCC_PLLI2S_ENABLE();
}

/* USER CODE BEGIN 4 */

/**
 * @brief HAL_SYSTICK_Callback()
 * SW timer triggered every 1ms.
 */
void HAL_SYSTICK_Callback(void)
{
  flag_1ms = 1;
  /*update counters*/
  if(counter_10ms<9)  {    counter_10ms++;  }
  else  {    counter_10ms = 0;    flag_10ms = 1;  }
  if(counter_50ms<49)  {    counter_50ms++;  }
  else  {    counter_50ms = 0;    flag_50ms = 1;  }

  if(counter_100ms<99)  {    counter_100ms++;  }
  else  {    counter_100ms = 0;    flag_100ms = 1;
	if(counter_200ms<1)	{	  counter_200ms++;	}
	else	{	  counter_200ms = 0;	  flag_200ms = 1;	}
	if(counter_500ms<4)	{	  counter_500ms++;	}
	else	{	  counter_500ms = 0;	  flag_500ms = 1;	}
	if(counter_1000ms<9)	{	  counter_1000ms++;	}
	else	{	  counter_1000ms = 0;	  flag_1000ms = 1;	}
	if(counter_2000ms<19)	{	  counter_2000ms++;	}
	else	{	  counter_2000ms = 0;	  flag_2000ms = 1;	}
	if(counter_5000ms<49)	{	  counter_5000ms++;	}
	else	{	  counter_5000ms = 0;	  flag_5000ms = 1;	}
	if(counter_10s<99)	{	  counter_10s++;	}
	else	{	  counter_10s = 0;	  flag_10s = 1;	}
  }
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if(GPIO_Pin ==GPIO_PIN_13)
  {
	b_KeyNumber++;
	if(b_KeyNumber>=2)
	{
		b_KeyNumber = 0;
	}

	sprintf((char *)a_DtuInBuffer, "a simple package\r\n");
	b_DtuInBufferRxCnt = strlen((char *)a_DtuInBuffer);

  }
}

/* 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****/

4 試驗結果

開發板上面的指示燈亮了,同時使用仿真器觀察接收數組的內容:

 參考資料:

1、STM32F107規格書,https://www.st.com/resource/en/datasheet/stm32f107rc.pdf

2、STM32F107參考手冊,https://www.st.com/resource/en/reference_manual/cd00171190.pdf

3、硬石YS-F1Pro開發板資料,http://www.ing10bbs.com/forum.php?mod=viewthread&tid=1458&extra=page%3D1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章