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>© 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