实现思路
除了传统的bootloader外,在boot区还要实现将app从串口发送出去的功能
- bootloader:将新的APP的bin文件从上位机中下载下来到flash区以及将APP发送到板子上的bootloader。
- 离线升级工具:与上位机通讯的bootloader和通过按键选择通信方式的多个bootloader。
- 上位机
调试经验
- 上位机下载APP至离线升级工具时,所使用的串口配置与工具发送APP至产品时所使用的串口配置,两者应慎重考虑,不能有重复定义的变量。
//串口1
#define USARTy UART3
#define UART1_TX_Port GPIOB
#define UART1_TX_Pin GPIO_PIN_10
#define UART1_TX_AF GPIO_AF10_UART3
#define UART1_RX_Port GPIOB
#define UART1_RX_Pin GPIO_PIN_11
#define UART1_RX_AF GPIO_AF10_UART3
//串口2
#define USARTy_IRQHandler USART1_IRQHandler
#ifdef _USART1_USART2_
//#define USARTy USART1
#define USARTy_CLK RCC_APB2_PERIPH_USART1
#define USARTy_GPIO GPIOA
#define USARTy_GPIO_CLK RCC_AHB_PERIPH_GPIOA
#define USARTy_RxPin GPIO_PIN_10
#define USARTy_TxPin GPIO_PIN_9
#define USARTy_Rx_GPIO_AF GPIO_AF5_USART1
#define USARTy_Tx_GPIO_AF GPIO_AF5_USART1
- 慎重考虑flash空间的大小,离线工具功能加bootloader功能,占用的flash空间远高于传统的bootloader,当flash不超过64k且boot为23k时,APP大小不能够超过40k,否则程序会停止运行。
- 重定义及隐式声明告警一定清。
- 用定时器实现串口的接收超时中断功能,需要仔细计算定时器的超时时间。
如果时钟从头开始配置,需要从头开始计算时钟频率;
如果时钟没有从头开始配置,使用默认值,比如如下代码中SYSCLK默认为128k,由于SYSCLK到AHB的时钟同样没有配置,HCLK默认为128MHz。
时钟计算:
BSTIMClockFrequency = Common_BSTIM_RCC_Initialize(TIM6, RCC_HCLK_DIV4):表明将HCLK四分频,经过APB1后的频率变为32MHz,
Common_TIM_Base_Initialize(TIM6, 32768, 0):表明此时的分频系数为0,根据430规格书,当分频系数为0时自动+1,根据时钟树当Prescaler=1时,分频系数为1,因此所使用的TIM6的时钟频率为32MHz。
typedef struct
{
uint32_t SysclkFreq; /* returns SYSCLK clock frequency expressed in Hz */
uint32_t HclkFreq; /* returns HCLK clock frequency expressed in Hz */
uint32_t Pclk1Freq; /* returns PCLK1 clock frequency expressed in Hz */
uint32_t Pclk2Freq; /* returns PCLK2 clock frequency expressed in Hz */
uint32_t AdcPllClkFreq; /* returns ADCPLLCLK clock frequency expressed in Hz */
uint32_t AdcHclkFreq; /* returns ADCHCLK clock frequency expressed in Hz */
} RCC_ClocksType;
void Tim_Config(void)
{
/* System Clocks Configuration */
BSTIMClockFrequency = Common_BSTIM_RCC_Initialize(TIM6, RCC_HCLK_DIV4);
/* NVIC Configuration */
Common_TIM_NVIC_Initialize(TIM6_IRQn, ENABLE);
/* Time base configuration, period = 65535, prescaler = prescaler */
Common_TIM_Base_Initialize(TIM6, 32768, 0);
TIM_Base_Reload_Mode_Set(TIM6, TIM_PSC_RELOAD_MODE_IMMEDIATE);
TIM_Interrupt_Enable(TIM6, TIM_INT_UPDATE);
// TIM_On(TIM6);
}
uint32_t SysTick_InitConfig(uint32_t ms)
{
RCC_Clocks_Frequencies_Value_Get(&RCC_Clocks);
}
当TIM6定时器的频率为32MHz时,它所使能的中断计算过程如下:
T = 1/32MHz = 31.25ns
32.25ns × 32768 = 1.024ms
计数5次算溢出:
1.024 × 5 = 5.12ms
当超过5ms没有新数据接收的时候默认数据传输完毕。
void TIM6_IRQHandler(void)
{
if (TIM_Interrupt_Status_Get(TIM6, TIM_INT_UPDATE) != RESET)
{
TIM_Interrupt_Status_Clear(TIM6, TIM_INT_UPDATE);
if(RxCntCur!=0)
{
if(RxCntBk!=RxCntCur)//表示有接收到数据 上次接收到的字节数不等于当前接收到的字节数
{
RxCntBk=RxCntCur;
RecTimeOutCnt=0;
}
else //当前无新数据接收 RxCntBk==RxCntCur
{
RecTimeOutCnt++; //接收超时计数
if(RecTimeOutCnt>=5)//接收完成一帧数据
{
/
RxCntCur=0;
RxCntBk=0;
RecTimeOutCnt=0;
g_RxOverFlag=1;
TIM_Off(TIM6);
}
}
}
else
{
RxCntBk=0;
RecTimeOutCnt=0;
}
}
}
- 对同一按键信号,用中断处理,或者在while循环中实时读取电平状态,慎重考虑两种方式是否可以同时存在。
//可行代码
void EXTI9_5_IRQHandler(void)
{
if (RESET != EXTI_Interrupt_Status_Get(KEY_INPUT_EXTI_LINE_U))
{
g_key_on=1;
u_update_key_flag = 1;
EXTI_Interrupt_Status_Clear(KEY_INPUT_EXTI_LINE_C | KEY_INPUT_EXTI_LINE_U);
}
if (RESET != EXTI_Interrupt_Status_Get(KEY_INPUT_EXTI_LINE_C))
{
g_key_on=1;
c_update_key_flag = 1;
EXTI_Interrupt_Status_Clear(KEY_INPUT_EXTI_LINE_C | KEY_INPUT_EXTI_LINE_U);
}
}
if(u_update_key_flag == 1)
{
u_update_key_flag = 0;
UART_Request_Update_Flow(); // 开始UART升级流程
}
/*CAN升级*/
if(c_update_key_flag == 1)
{
c_update_key_flag = 0;
CAN_Request_Update_Flow(); // 开始CAN升级流程
}
//不可行代码
void EXTI9_5_IRQHandler(void)
{
if (RESET != EXTI_Interrupt_Status_Get(KEY_INPUT_EXTI_LINE))
{
g_key_on=1;
EXTI_Interrupt_Status_Clear(KEY_INPUT_EXTI_LINE);
}
}
if(GPIO_Input_Pin_Data_Get(KEY_INPUT_UART_PORT, KEY_INPUT_UART_PIN) == PIN_SET)
{
UART_Request_Update_Flow(); // 开始UART升级流程
}
/*CAN升级*/
if(GPIO_Input_Pin_Data_Get(KEY_INPUT_CAN_PORT, KEY_INPUT_CAN_PIN) == PIN_SET)
{
CAN_Request_Update_Flow(); // 开始CAN升级流程
}
- 串口数据发送不了,有可能是没有配置GPIO的时钟
附加代码段:
main.c
/*****************************************************************************
* Copyright (c) 2019, Nations Technologies Inc.
*
* All rights reserved.
* ****************************************************************************
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Nations' name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL NATIONS 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.
* ****************************************************************************/
/**
*\*\file main.c
*\*\author Nations
*\*\version v1.0.0
*\*\copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
**/
#include "main.h"
#include <math.h>
#include "uart.h"
#include "can.h"
#include "time.h"
#include "led.h"
#include "key.h"
#include "u_app_data.h"
#include "c_app_data.h"
#include "n32g430.h"
#include "BK_Command.h"
#include "n32g430_it.h"
// typedef void (*iapfun)(void); //定义一个函数类型的参数.
// iapfun jump2app;
uint8_t Uart1_RxBuf[256]={0x00};
uint16_t RxIndex=0;
volatile uint8_t g_RxOverFlag=0;//串口接收一帧完成标志
uint16_t RxCntCur=0;//当前接收的字节数
uint16_t RxCntBk=0; //上次接收的字节数
uint8_t RecTimeOutCnt=0;//接收超时计数
USART_InitType USART_InitStructure;
RCC_ClocksType RCC_Clocks;
DMA_InitType DMA_InitStructureTx;
volatile uint32_t *p;
volatile uint16_t *p1;
uint16_t PrescalerValue = 0;
uint8_t g_RetFailFlagToPC=0;
// /***********************************
// *名称:
// *功能:
// *参数:
// *日期:
// ************************************/
// void boot_write(void)
// {
// /* System Clocks Configuration */
// RCC_Configuration();
// NVIC_Configuration();
// GPIO_Configuration();
// // DMA_Configuration();
// Uart_Config();//
// Tim_Config();
// __enable_irq();
// //
// IWDG_Config(IWDG_CONFIG_PRESCALER_DIV128, 61*8);//约17S
// while(1)
// {
// #ifdef _DEBUG
// IWDG_ReloadKey();
// #endif
// Uart_RcvDataProg();
// }
// }
/**
* @brief Configures the different system clocks.
*/
void RCC_Configuration(void)
{
/* DMA clock enable */
// RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA, ENABLE);
/* Enable GPIO clock */
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA | RCC_AHB_PERIPH_GPIOB);
/* Enable USART1 and UART3 Clock */
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_USART1 | RCC_APB2_PERIPH_UART3);
}
/**
* @brief Configures the nested vectored interrupt controller.
*/
void NVIC_Configuration(void)
{
NVIC_InitType NVIC_InitStructure;
/* Enable the USARTy_Tx DMA Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//uart1 irq
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Initializes(&NVIC_InitStructure);
/* Enable the TIM1 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Initializes(&NVIC_InitStructure);
}
/**
* @brief Configures the different GPIO ports.
*/
void GPIO_Configuration(void)
{
GPIO_InitType GPIO_InitStructure;
/* Initialize GPIO_InitStructure */
GPIO_Structure_Initialize(&GPIO_InitStructure);
/* Configure USARTy Tx as alternate function push-pull */
GPIO_InitStructure.Pin = USARTy_TxPin;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.GPIO_Alternate = USARTy_Tx_GPIO_AF;
GPIO_Peripheral_Initialize(USARTy_GPIO, &GPIO_InitStructure);
/* Configure USARTx Rx as alternate function push-pull */
GPIO_InitStructure.Pin = USARTy_RxPin;
GPIO_InitStructure.GPIO_Alternate = USARTy_Rx_GPIO_AF;
GPIO_Peripheral_Initialize(USARTy_GPIO, &GPIO_InitStructure);
//
//
// GPIO_InitStructure.Pin = GPIO_PIN_6;
// GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
// GPIO_InitStructure.GPIO_Current = GPIO_DC_LOW;
// GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
//用于测试
}
/***********************************
*名称:
*功能:
*参数:
*日期:
************************************/
void Uart_Config(void)
{
/* USARTy and USARTz configuration ------------------------------------------------------*/
USART_InitStructure.BaudRate = 9600; //1s能发送19200个比特位
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
/* Configure USART1 */
USART_Initializes(USART1, &USART_InitStructure);
// USART_EnableDMA(USARTy,USART_DMAREQ_TX, ENABLE);
// DMA_EnableChannel(USARTy_Tx_DMA_Channel,DISABLE);
//
USART_Interrupt_Status_Clear(USART1, USART_FLAG_TXC|USART_FLAG_RXDNE);
USART_Flag_Clear(USART1, USART_INT_TXC|USART_INT_RXDNE);
/* Enable USARTy Receive interrupt */
USART_Interrput_Enable(USART1, USART_INT_RXDNE);//允许接收中断
USART_Enable(USART1);
}
/**
*\*\name Common_BSTIM_RCC_Initialize.
*\*\param TIMx :
*\*\ - TIM6
*\*\param hclk_division
*\*\ - RCC_HCLK_DIV1
*\*\ - RCC_HCLK_DIV2
*\*\ - RCC_HCLK_DIV4
*\*\ - RCC_HCLK_DIV8
*\*\ - RCC_HCLK_DIV16
*\*\return uint32_t
**/
uint32_t Common_BSTIM_RCC_Initialize(TIM_Module *TIMx, uint32_t hclk_division)
{
uint32_t BSTIM_clock;
RCC_ClocksType RCC_Clocks;
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA | RCC_AHB_PERIPH_GPIOB| RCC_AHB_PERIPH_GPIOC
| RCC_AHB_PERIPH_GPIOD);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
RCC_Pclk1_Config(hclk_division);
RCC_APB1_Peripheral_Clock_Enable(RCC_APB1_PERIPH_TIM6);
RCC_Clocks_Frequencies_Value_Get(&RCC_Clocks);
if(RCC_Clocks.HclkFreq > RCC_Clocks.Pclk1Freq)
{
BSTIM_clock = RCC_Clocks.Pclk1Freq * 2;
}
else
{
BSTIM_clock = RCC_Clocks.Pclk1Freq;
}
return BSTIM_clock;
}
/**
*\*\name Common_TIM_NVIC_Initialize.
*\*\param IRQ_number :
*\*\ - TIM1_BRK_IRQn
*\*\ - TIM1_UP_IRQn
*\*\ - TIM1_TRG_COM_IRQn
*\*\ - TIM1_CC_IRQn
*\*\ - TIM2_IRQn
*\*\ - TIM3_IRQn
*\*\ - TIM4_IRQn
*\*\ - TIM8_BRK_IRQn
*\*\ - TIM8_UP_IRQn
*\*\ - TIM8_TRG_COM_IRQn
*\*\ - TIM8_CC_IRQn
*\*\ - TIM5_IRQn
*\*\ - TIM6_IRQ
*\*\param command
*\*\ - ENABLE
*\*\ - DISABLE
*\*\return none
**/
void Common_TIM_NVIC_Initialize(IRQn_Type IRQ_number, FunctionalState command)
{
NVIC_InitType NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = IRQ_number;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
if(ENABLE == command)
{
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
}
else
{
NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
}
NVIC_Initializes(&NVIC_InitStructure);
}
static TIM_TimeBaseInitType TIM_TimeBaseStructure;
/**
*\*\name Common_TIM_Base_Initialize.
*\*\param TIMx :
*\*\ - TIM1
*\*\ - TIM2
*\*\ - TIM3
*\*\ - TIM4
*\*\ - TIM5
*\*\ - TIM6
*\*\param period
*\*\ - [1, 0xffff]
*\*\param prescaler
*\*\ - [0, 0xffff]
*\*\return none
**/
void Common_TIM_Base_Initialize(TIM_Module *TIMx, uint16_t period, uint16_t prescaler)
{
TIM_Base_Struct_Initialize(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.Period = period;
TIM_TimeBaseStructure.Prescaler = prescaler;
TIM_TimeBaseStructure.ClkDiv = 0;
TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP;
TIM_Base_Initialize(TIMx, &TIM_TimeBaseStructure);
}
uint32_t BSTIMClockFrequency = 0;
void Tim_Config(void)
{
/* System Clocks Configuration */
BSTIMClockFrequency = Common_BSTIM_RCC_Initialize(TIM6, RCC_HCLK_DIV4);
/* NVIC Configuration */
Common_TIM_NVIC_Initialize(TIM6_IRQn, ENABLE);
/* Time base configuration, period = 65535, prescaler = prescaler */
Common_TIM_Base_Initialize(TIM6, 32768, 0);
TIM_Base_Reload_Mode_Set(TIM6, TIM_PSC_RELOAD_MODE_IMMEDIATE);
TIM_Interrupt_Enable(TIM6, TIM_INT_UPDATE);
// TIM_On(TIM6);
}
void IWDG_ReloadKey(void)
{
IWDG->KEY = KEY_RELOAD_COUNTER;
}
void IWDG_Config(uint8_t IWDG_prescaler, uint16_t reload_value)
{
//DBG_ConfigPeriph(DBG_IWDG_STOP, ENABLE);//在调试模式下禁用IWDG
IWDG_Write_Protection_Disable();//开启对IWDG_PR和IWDG_RLR寄存器的写访问
IWDG_Prescaler_Division_Set(IWDG_prescaler);//30KHZ 分频系数
/* Sets IWDG reload value */
/* Set counter reload value to obtain x second IWDG TimeOut.
Counter Reload Value Time = x(second)/IWDG counter clock period
= x(second) / (LSI/IWDG_prescaler)
*/
IWDG_Counter_Reload(reload_value);//
/* Reload counter with IWDG_PREDIV value in IWDG_RELV register to prevent reset */
/* Reload IWDG counter */
IWDG_Key_Reload();
/* Enable IWDG (the LSI oscillator will be enabled by hardware) */
IWDG_Enable();
}
/***********************************
*名称:
*功能:
*参数:
*日期:
************************************/
void Delay_us(uint32_t us)
{
uint32_t i,j;
for(i=0;i<us;i++)
{
#ifdef _DEBUG
IWDG_ReloadKey();
#endif
for(j=0;j<1000;j++)
{
;
}
}
}
// SENDING_RESULT g_sengding_result = SENDING_FAIL;
volatile CAN_RECEIVE_RESULT g_rx_flag = UNRECEIVED; // UNRECEIVE
volatile uint8_t g_key_on = 0;
/**
*\*\name main
*\*\fun Main program.
*\*\param none
*\*\return none
**/
int main(void)
{
// config 1ms Systick
SysTick_InitConfig(1);
// LedInit(LED_RED_PORT, LED_RED_PIN);
// LedInit(LED_BLUE_PORT, LED_BLUE_PIN);
// LedInit(LED_GREEN_PORT, LED_GREEN_PIN);
// LedInit();
RCC_Configuration();
KeyInputExtiInit(KEY_INPUT_UART_PORT, KEY_INPUT_UART_PIN);
KeyInputExtiInit(KEY_INPUT_CAN_PORT, KEY_INPUT_CAN_PIN);
/* UART and CAN configure */
UartInit();
CAN_CONFIG();
NVIC_Configuration();
GPIO_Configuration();
// APP下载UARTS1
Uart_Config();//
Tim_Config();
__enable_irq();
//
#ifdef _DEBUG
IWDG_Config(IWDG_CONFIG_PRESCALER_DIV128, 61*8);//约17S
#endif
while (1)
{
// RCC_Clocks_Frequencies_Value_Get(&RCC_Clocks);
// boot_write();
#ifdef _DEBUG
IWDG_ReloadKey();
#endif
Uart_RcvDataProg();
if (g_key_on==0)
{
continue;//等待按下按键
}
// Get_FlashAPPCodeCrc();
/*UART升级*/
if(u_update_key_flag == 1)
{
// TIM_Compare2_Set(TIM3,2500); //蓝 闪
// TIM_Compare2_Set(TIM2,0); //红 灭
// // LedOff(LED_GREEN_PORT, LED_GREEN_PIN); //绿 灭
u_update_key_flag = 0;
UART_Request_Update_Flow(); // 开始UART升级流程
}
/*CAN升级*/
if(c_update_key_flag == 1)
{
// TIM_Compare2_Set(TIM3,2500); //蓝 闪
// TIM_Compare2_Set(TIM2,0); //红 灭
// // LedOff(LED_GREEN_PORT, LED_GREEN_PIN); //绿 灭
c_update_key_flag = 0;
CAN_Request_Update_Flow(); // 开始CAN升级流程
}
g_key_on=0; //正常跑完流程,按键状态清零
// TIM_Compare2_Set(TIM3,0); //蓝 灭
}
}
n32g430_it.c
/*****************************************************************************
* Copyright (c) 2019, Nations Technologies Inc.
*
* All rights reserved.
* ****************************************************************************
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Nations' name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL NATIONS 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.
* ****************************************************************************/
/**
*\*\file n32g430_it.c
*\*\author Nations
*\*\version v1.0.0
*\*\copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
**/
#include "n32g430_it.h"
#include "main.h"
// uint8_t RxCounter = 0;
// extern uint8_t RxBuffer2[];
// extern uint8_t NbrOfDataToRead;
/** Cortex-M4 Processor Exceptions Handlers **/
/**
*\*\name NMI_Handler.
*\*\fun This function handles NMI exception.
*\*\param none
*\*\return none
**/
void NMI_Handler(void)
{
}
/**
*\*\name HardFault_Handler.
*\*\fun This function handles Hard Fault exception.
*\*\param none
*\*\return none
**/
void HardFault_Handler(void)
{
/* Go to infinite loop when Hard Fault exception occurs */
while (1)
{
}
}
/**
*\*\name MemManage_Handler.
*\*\fun This function handles Memory Manage exception.
*\*\param none
*\*\return none
**/
void MemManage_Handler(void)
{
/* Go to infinite loop when Memory Manage exception occurs */
while (1)
{
}
}
/**
*\*\name BusFault_Handler.
*\*\fun This function handles Bus Fault exception.
*\*\param none
*\*\return none
**/
void BusFault_Handler(void)
{
/* Go to infinite loop when Bus Fault exception occurs */
while (1)
{
}
}
/**
*\*\name UsageFault_Handler.
*\*\fun This function handles Usage Fault exception.
*\*\param none
*\*\return none
**/
void UsageFault_Handler(void)
{
/* Go to infinite loop when Usage Fault exception occurs */
while (1)
{
}
}
/**
*\*\name SVC_Handler.
*\*\fun This function handles SVCall exception.
*\*\param none
*\*\return none
**/
void SVC_Handler(void)
{
}
/**
*\*\name PendSV_Handler.
*\*\fun This function handles PendSV_Handler exception.
*\*\param none
*\*\return none
**/
void PendSV_Handler(void)
{
}
/**
*\*\name DebugMon_Handler.
*\*\fun This function handles Debug Monitor exception.
*\*\param none
*\*\return none
**/
void DebugMon_Handler(void)
{
}
/**
*\*\name SysTick_Handler.
*\*\fun This function handles SysTick Handler.
*\*\param none
*\*\return none
**/
void SysTick_Handler(void)
{
}
/* N32G430 Peripherals Interrupt Handlers, interrupt handler's name please refer to the startup file (startup_n32g430.s). */
/**
*\*\name CAN_RX0_IRQHandler
*\*\fun CAN FIFO0 receive interrupt.
*\*\param none
*\*\return none
**/
void CAN_RX0_IRQHandler(void)
{
CAN_Message_Receive(CAN, CAN_FIFO0, &CAN_RxMessage); // 从FIFO读取8个字节数据
// if(Get_Sending_Result(CAN_RxMessage.Data)==SENGDING_OK)
// {
// g_sengding_result= SENGDING_OK; //发送写入成功
// }else
// {
// g_sengding_result= SENDING_FAIL;//发送写入失败
// }
g_rx_flag = RECEIVED; //表示已经接收到数据
}
/** N32G430 Peripherals Interrupt Handlers, interrupt handler's name please refer to the startup file (startup_n32g430.s) **/
/**
*\*\name EXTI9_5_IRQHandler.
*\*\fun External lines 5 to 9 interrupt.
*\*\param none
*\*\return none
**/
uint8_t u_update_key_flag = 0, c_update_key_flag = 0;
void EXTI9_5_IRQHandler(void)
{
if (RESET != EXTI_Interrupt_Status_Get(KEY_INPUT_EXTI_LINE_U))
{
g_key_on=1;
u_update_key_flag = 1;
EXTI_Interrupt_Status_Clear(KEY_INPUT_EXTI_LINE_C | KEY_INPUT_EXTI_LINE_U);
}
if (RESET != EXTI_Interrupt_Status_Get(KEY_INPUT_EXTI_LINE_C))
{
g_key_on=1;
c_update_key_flag = 1;
EXTI_Interrupt_Status_Clear(KEY_INPUT_EXTI_LINE_C | KEY_INPUT_EXTI_LINE_U);
}
}
/******************************************************************************/
/* N32G430 Peripherals Interrupt Handlers */
/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */
/* available peripheral interrupt handler's name please refer to the startup */
/* file (startup_n32g430.s). */
/******************************************************************************/
/**
* @brief This function handles USARTy_Tx or USARTz_Rx DMA global interrupt request.
*/
extern uint8_t g_RetFailFlagToPC;
void USARTy_IRQHandler(void)
{
volatile uint8_t tmp=0;
if (USART_Flag_Status_Get(USART1, USART_INT_RXDNE) != RESET)
{
/* Read one byte from the receive data register */
USART_Interrupt_Status_Clear(USART1, USART_INT_RXDNE);
//如果当前还没有接收到数据,则第一个数据必须是0xF1
if(0==RxCntCur)
{
tmp = USART_Data_Receive(USART1);
if(0xF1==tmp) //接收到的是帧头标志,同步到帧头
{
RxIndex=0;
Uart1_RxBuf[RxIndex]=tmp;
RxIndex++;
RxCntCur++;
RecTimeOutCnt=0; //超时计数清零
TIM_On(TIM6);
}
else //返回失败信息,此时有效接收字节RxCntCur仍然是0x00
{
g_RetFailFlagToPC=1;
}
}
//成功接收到帧头之后,RxCntCur才会递增
else
{
Uart1_RxBuf[RxIndex]=USART_Data_Receive(USART1);
RxIndex++;
RxCntCur++;
RecTimeOutCnt=0; //超时计数清零
if(RxCntCur>=200) //数组溢出,表明数据有错
{
RxCntCur=0;
RxCntBk=0;
g_RetFailFlagToPC=1;
g_RxOverFlag=0;
}
}
}
if (USART_Flag_Status_Get(USART1, USART_INT_ERRF) != RESET) {
USART_Interrupt_Status_Clear(USART1, USART_INT_ERRF);
}
if (USART_Flag_Status_Get(USART1, USART_INT_OREF) != RESET) {
USART_Interrupt_Status_Clear(USART1, USART_INT_OREF);
}
}
// void TIM1_BRK_IRQHandler(void)
// {
// TIM1_BRK_UP_TRG_COM_IRQHandler();
// }
// void TIM1_UP_IRQHandler(void)
// {
// TIM1_BRK_UP_TRG_COM_IRQHandler();
// }
// void TIM1_TRG_COM_IRQHandler(void)
// {
// TIM1_BRK_UP_TRG_COM_IRQHandler();
// }
void TIM6_IRQHandler(void)
{
if (TIM_Interrupt_Status_Get(TIM6, TIM_INT_UPDATE) != RESET)
{
TIM_Interrupt_Status_Clear(TIM6, TIM_INT_UPDATE);
if(RxCntCur!=0)
{
if(RxCntBk!=RxCntCur)//表示有接收到数据 上次接收到的字节数不等于当前接收到的字节数
{
RxCntBk=RxCntCur;
RecTimeOutCnt=0;
}
else //当前无新数据接收 RxCntBk==RxCntCur
{
RecTimeOutCnt++; //接收超时计数
if(RecTimeOutCnt>=5)//接收完成一帧数据
{
/
RxCntCur=0;
RxCntBk=0;
RecTimeOutCnt=0;
g_RxOverFlag=1;
TIM_Off(TIM6);
}
}
}
else
{
RxCntBk=0;
RecTimeOutCnt=0;
}
}
}
// void TIM1_BRK_UP_TRG_COM_IRQHandler(void)
// {
// if (TIM_Interrupt_Status_Get(TIM1, TIM_INT_UPDATE) != RESET)
// {
// TIM_Interrupt_Status_Clear(TIM1, TIM_INT_UPDATE);
// if(RxCntCur!=0)
// {
// if(RxCntBk!=RxCntCur)//表示有接收到数据 上次接收到的字节数不等于当前接收到的字节数
// {
// RxCntBk=RxCntCur;
// RecTimeOutCnt=0;
// }
// else //当前无新数据接收 RxCntBk==RxCntCur
// {
// RecTimeOutCnt++; //接收超时计数
// if(RecTimeOutCnt>=10)//接收完成一帧数据
// {
// /
// RxCntCur=0;
// RxCntBk=0;
// RecTimeOutCnt=0;
// g_RxOverFlag=1;
// }
// }
// }
// else
// {
// RxCntBk=0;
// RecTimeOutCnt=0;
// }
//
// // GPIO_WriteBit(GPIOA, GPIO_PIN_6, (Bit_OperateType)(1 - GPIO_ReadOutputDataBit(GPIOA, GPIO_PIN_6)));
// }
// }
uart.c
/*****************************************************************************
* Copyright (c) 2019, Nations Technologies Inc.
*
* All rights reserved.
* ****************************************************************************
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Nations' name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL NATIONS 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.
* ****************************************************************************/
/**
*\*\file can_config.c
*\*\author Nations
*\*\version v1.0.0
*\*\copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
**/
#include "uart.h"
#include "main.h"
#include "common.h"
#include <string.h>
// #include <math.h>
// #include <stdlib.h>
// #include <string.h>
USART_InitType UART3_InitStructure;
// uint8_t UartReadBuf[COMNUM][UARTRESIZE];
uint8_t *pUartSendBuf[COMNUM];
uint16_t SendLen[COMNUM],SendCount[COMNUM];
uint16_t ReceiveLen[COMNUM];
uint8_t TxMark[COMNUM],RxMark[COMNUM];
uint8_t RxEndDelay[COMNUM];
//uint8_t g_device_id = 0x01; // 升级的设备ID
//uint8_t receive_data[28] = {0};
/**
*\*\name UartInit.
*\*\fun Configures the Uart.
*\*\param none
*\*\return none
**/
void UartInit(void) //主函数初始化调用一次
{
GPIO_InitType GPIO_InitStructure;
GPIO_Structure_Initialize(&GPIO_InitStructure);
/* Configure USART Tx as alternate function push-pull */
GPIO_InitStructure.Pin = UART1_TX_Pin;//PB10
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.GPIO_Alternate = UART1_TX_AF;
GPIO_Peripheral_Initialize(UART1_TX_Port, &GPIO_InitStructure);
/* Configure USART Rx as alternate function push-pull */
GPIO_InitStructure.Pin = UART1_RX_Pin;//PB11
GPIO_InitStructure.GPIO_Alternate = UART1_RX_AF;
GPIO_Peripheral_Initialize(UART1_RX_Port, &GPIO_InitStructure);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_UART3);
// UartOpen(USART1, 115200);
UartOpen(USARTy , 9600);
}
void UartOpen(USART_Module* USARTn, u32 BaudRate) //uart初始化,使能打开
{
USART_InitType USART_InitStructure;
/* USART configuration ------------------------------------------------------*/
USART_InitStructure.BaudRate = BaudRate;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
/* Configure USART */
USART_Initializes(USARTn, &USART_InitStructure);
// /* Enable USART Receive and Transmit interrupts */
// USART_Interrput_Enable(USARTn, USART_INT_RXDNE);
// // USART_ConfigInt(USARTn, USART_INT_TXC, ENABLE);
USART_Interrupt_Status_Clear(USARTn, USART_FLAG_TXC|USART_FLAG_RXDNE);
USART_Flag_Clear(USARTn, USART_INT_TXC|USART_INT_RXDNE);
/* Enable the USART */
USART_Enable(USARTn);
}
//----------------------------------------------------------
/**
* @brief 发送 开始升级 命令
*
* @param uart3_id
* @param data 2个字节数据
*/
void U_Send_Start_Update_Message(uint8_t uart3_id, uint8_t device_id)
{
uint8_t func_code = U_UPDATE_TYPE_FUN_CODE_WRITE; // 功能码:写入 0x90 ,读取0x91
uint8_t fun_ext_code = U_UPDATE_TYPE_FUN_EXT_CODE_START_UPDATE; // 功能扩展码: 0x00
uint8_t headerR = UPDATE_TYPE_HEAdER_REQUEST; // 帧头请求:0xF1
uint8_t endR = UPDATE_TYPE_END_REQUEST; // 帧尾请求:0xF2
uint8_t data[2] = {0x90, 0x09};
U_Send_Frame_Data(headerR, uart3_id, device_id, func_code, fun_ext_code, 2, data, endR);
}
/**
* @brief 发送 快速升级(预留) 命令:改变波特率
*
* @param uart3_id
* @param data 2个字节数据
*/
void U_Send_Fast_Update_Message(uint8_t uart3_id, uint8_t device_id)
{
uint8_t func_code = U_UPDATE_TYPE_FUN_CODE_WRITE; // 功能码:写入 0x90 ,读取0x91
uint8_t fun_ext_code = U_UPDATE_TYPE_FUN_EXT_CODE_FAST_UPDATE; // 功能扩展码: 0x02
uint8_t headerR = UPDATE_TYPE_HEAdER_REQUEST; // 帧头请求:0xF1
uint8_t endR = UPDATE_TYPE_END_REQUEST; // 帧尾请求:0xF2
uint8_t data[2] = {0x92, 0x29};
U_Send_Frame_Data(headerR, uart3_id, device_id, func_code, fun_ext_code, 2, data, endR);
}
/**
* @brief 发送 准备升级 命令,擦除APP Flash区域,同时将APP信息存FLASH Boot信息区域
*
* @param uart3_id
* @param device_id 设备ID
* @param crc16 app数据的crc16
* @param app_data_pack_total_num app数据的总包数
* @param project_id 项目ID
*/
void U_Send_Ready_Update_Message(uint8_t uart3_id, uint8_t device_id, uint16_t app_data_crc16, uint16_t app_data_pack_total_num, uint32_t project_id)
{
uint8_t func_code = U_UPDATE_TYPE_FUN_CODE_WRITE; // 功能码:写入 0x90 ,读取0x91
uint8_t fun_ext_code = U_UPDATE_TYPE_FUN_EXT_CODE_READY_UPDATE; // 功能扩展码: 0x04
uint8_t headerR = UPDATE_TYPE_HEAdER_REQUEST; // 帧头请求:0xF1
uint8_t endR = UPDATE_TYPE_END_REQUEST; // 帧尾请求:0xF2
uint8_t data[8] = {0};
data[0] = app_data_crc16 & 0xFF; // crc16 低8位
data[1] = app_data_crc16 >> 8; // crc16高8位
data[2] = app_data_pack_total_num & 0xFF; // app_data_pack_total_num 低8位
data[3] = (app_data_pack_total_num >> 8) & 0xFF; // app_data_pack_total_num 高8位
data[4] = project_id & 0xFF; // project_id bit0-bit7
data[5] = (project_id >> 8) & 0xFF; // project_id bit8-bit15
data[6] = (project_id >> 16) & 0xFF; // project_id bit16-bit7
data[7] = (project_id >> 24) & 0xFF; // project_id bit24-bit32
U_Send_Frame_Data(headerR, uart3_id, device_id, func_code, fun_ext_code, 8, data, endR);
}
/**
* @brief 发送 APP数据包
*
* @param uart3_id
* @param device_id 设备ID
* @param app_data_num APP数据包序号,从0开始,0表示第一包
* @param data 128个字节APP数据
*/
void U_Send_Update_Data_Message(uint8_t uart3_id, uint8_t device_id, uint16_t app_data_num, uint8_t *data)
{
uint8_t data_length = 131; //(2字节数据分包序号+128个字节数据+当前包的固件数据的CRC8)
uint8_t func_code = U_UPDATE_TYPE_FUN_CODE_WRITE; // 功能码:写入 0x90 ,读取0x91
uint8_t fun_ext_code = U_UPDATE_TYPE_FUN_EXT_CODE_UPDATE_DATA; // 功能扩展码: 0x0C
uint8_t headerR = UPDATE_TYPE_HEAdER_REQUEST; // 帧头请求:0xF1
uint8_t endR = UPDATE_TYPE_END_REQUEST; // 帧尾请求:0xF2
uint8_t new_data[131] = {0}; // 声明一个固定大小的数组,用于存储新的数据
//uint8_t *new_data = (uint8_t *)malloc(data_length);
new_data[0] = app_data_num & 0xFF; // 数据包序号 app_data_num 低8位
new_data[1] = (app_data_num >> 8) & 0xFF; // 数据包序号 app_data_num 高8位
memcpy(new_data + 2, data, 128); // 将传入的数据(128字节)复制到 new_data 数组的偏移为2的位置。
new_data[data_length - 1] = crc8_check(new_data + 2, 128); // 128个字节数据的CRC 计算并将数据的CRC8校验结果存储在 new_data 数组的最后一个位置。
U_Send_Frame_Data(headerR, uart3_id, device_id, func_code, fun_ext_code, data_length, new_data, endR);
//free(new_data); // 释放内存
}
/**
* @brief 升级完成,
*
* @param can_id
* @param device_id 设备ID
* @param data 2个字节数据
*/
void U_Send_Finish_Update_Message(uint8_t uart3_id, uint8_t device_id)
{
uint8_t func_code = U_UPDATE_TYPE_FUN_CODE_WRITE; // 功能码:写入 0x90 ,读取0x91
uint8_t fun_ext_code = U_UPDATE_TYPE_FUN_EXT_CODE_FINISH_UPDATE; // 功能扩展码: 0x8E
uint8_t headerR = UPDATE_TYPE_HEAdER_REQUEST; // 帧头请求:0xF1
uint8_t endR = UPDATE_TYPE_END_REQUEST; // 帧尾请求:0xF2
uint8_t data[2] = {0x8E, 0xE8};
U_Send_Frame_Data(headerR, uart3_id, device_id, func_code, fun_ext_code, 2, data, endR);
}
/**
* @brief CAN发送一帧数据,(即 帧头|识别码|功能码|功能扩展码|数据长度|数据|校验码|帧尾 格式)
*
* @param uart3_id UART3 ID
* @param device_id 设备码
* @param func_code 功能码
* @param fun_ext_code 功能扩展码
* @param data_length data_length 数据长度(最大为0xFF)
* @param data 数据 (数据长度最长只能是255个,0xFF)
*/
uint8_t pBuf[256] = {0};
void U_Send_Frame_Data(uint8_t headerR, uint16_t uart3_id, uint8_t device_id, uint8_t func_code, uint8_t fun_ext_code, uint8_t data_length, uint8_t *data, uint8_t endR)
{
// 发送一个UART包
pBuf[0] = headerR;
pBuf[1] = uart3_id;
pBuf[2] = device_id;
pBuf[3] = func_code;
pBuf[4] = fun_ext_code;
pBuf[5] = data_length;
uint16_t i = 0;
for(i = 0; i < data_length; i++)
{
pBuf[6+i] = data[i];
}
pBuf[data_length + 6] = crc8_check(&pBuf[1],data_length + 5);
pBuf[data_length + 7] = endR;
SysTick_Delay_Ms(1);
UartSendBuffer(pBuf, data_length + 8);
// 帧数据使用完成,释放内存
//free(pBuf);
}
/*****************************************************************************
函 数 名 : UartRxDisable
功能描述 : 单线通讯时,RX禁止
输入参数 :
返 回 值 :
*****************************************************************************/
void UartRxDisable(void)
{
USART_Interrput_Disable(USARTy, USART_INT_RXDNE); //USART_INT_RXDNE有数据可以读取
// Delay10us(10);
#ifdef SEND_INT_EN
USART_Interrput_Enable(USARTy, USART_INT_TXC); //USART_INT_TXC所有数据都已经发送完毕
#endif
TE_485();
}
void UartRxEnable(void)
{
// while (USART_GetFlagStatus(USART2, USART_FLAG_TXC) == RESET);
USART_Interrput_Enable(USARTy, USART_INT_RXDNE);
#ifdef SEND_INT_EN
USART_Interrput_Disable(USARTy, USART_INT_TXC);
#endif
RE_485();
}
/*****************************************************************************
函 数 名 : UartSendBuffer
功能描述 : Uart 发送
输入参数 :
返 回 值 :
*****************************************************************************/
uint8_t UartReadBuf[9] = {0};
void UartSendBuffer(uint8_t *pBuf, uint16_t length)
{
if(length ==0)
return;
pUartSendBuf[0] = pBuf;
SendCount[0] = 1;
SendLen[0] = length;
//TxMark[0] = VALID_MARK;
UartRxDisable();
//USART_Data_Send(USARTy, *pBuf);
USART_Flag_Clear(USARTy, USART_FLAG_RXDNE);
USART_Flag_Clear(USARTy, USART_FLAG_TXDE);
for (uint16_t i = 0; i < length; i++)
{
while ( 0 == USART_Flag_Status_Get(USARTy, USART_FLAG_TXDE)); //等待发送寄存器为空,立马发送下一个字节。
USART_Data_Send(USARTy, pBuf[i]);
// SysTick_Delay_Ms(1);
}
//TxMark[0] = VALID_MARK+1;
UartRxEnable();
for(uint8_t i = 0; i <= 8; i++ )
{
while ( 0 == USART_Flag_Status_Get(USARTy, USART_FLAG_RXDNE)); 等待接收寄存器不为空,立马读取数据,保证循环不会过快只读取到一个数据。
UartReadBuf[i] = USART_Data_Receive(USARTy);
// SysTick_Delay_Ms(1);
if(i == 8)
{
RxMark[0] = VALID_MARK;
}
}
}
// void USARTy_IRQHandler(void) //中断函数
// {
// if (USART_Interrupt_Status_Get(USARTy, USART_INT_RXDNE) != RESET)
// {
// if(ReceiveLen[0] >= UARTRESIZE) //大于最大接收字节数,清零
// {
// ReceiveLen[0] = 0;
// }
// UartReadBuf[0][ReceiveLen[0]]=USART_Data_Receive(USARTy); //数据存放位置
// ReceiveLen[0]++;
// RxEndDelay[0]= RXENDTIME; //接收最大时间为10ms //接收一个字节数据之后,10ms之内无数据,认为一帧数据结束
// }
// if (USART_Interrupt_Status_Get(USARTy, USART_INT_TXC) != RESET)
// {
// USART_Flag_Clear(USARTy, USART_FLAG_TXC);
// if(SendCount[0]!=SendLen[0])
// {
// USART_Data_Send(USARTy, *(pUartSendBuf[0]+SendCount[0])); //发送一个数据,计数器加1
// SendCount[0] ++;
// }
// else
// {
// TxMark[0] = VALID_MARK+1; //SendCount==SendLen相等,发送完成,改为接收状态
// UartRxEnable();
// }
// }
// USART_Flag_Clear(USARTy, USART_FLAG_CTSF|USART_FLAG_LINBD|USART_FLAG_TXDE|USART_FLAG_RXDNE|USART_FLAG_IDLEF|USART_FLAG_OREF|USART_FLAG_NEF|USART_FLAG_FEF|USART_FLAG_PEF);
// }
// void UartReTimer(void) //中断调用
// {
// if(RxEndDelay[0] !=0)
// {
// RxEndDelay[0]--;
// if(RxEndDelay[0]==1)
// {
// RxMark[0] = VALID_MARK; //接收完成
// }
// }
// }
// void UartDataDecode(void) //主函数调用
// {
// if(RxMark[0]==VALID_MARK)
// {
// RxMark[0] = UNVALID_MARK; //正在处理接收的数据
// // mb_Decode(UartReadBuf[0],ReceiveLen[0]); //boot升级
// modbus_Decode(UartReadBuf[0],ReceiveLen[0]); //收到的数据以及数据长度
// ReceiveLen[0] = 0; //处理完成后,将ReceiveLen[0]置为0,表示接收的数据已经处理完毕。
// }
// }
can.c
在这里插入代码片/*****************************************************************************
* Copyright (c) 2019, Nations Technologies Inc.
*
* All rights reserved.
* ****************************************************************************
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Nations' name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL NATIONS 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.
* ****************************************************************************/
/**
*\*\file can_config.c
*\*\author Nations
*\*\version v1.0.0
*\*\copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
**/
#include "can.h"
#include "main.h"
#include <math.h>
#include <stdlib.h>
#include "common.h"
#include <string.h>
CanTxMessage CAN_TxMessage;
CanRxMessage CAN_RxMessage;
CAN_InitType CAN_InitStructure;
CAN_FilterInitType CAN_FilterInitStructure;
//uint8_t g_device_id = 0x01; // 升级的设备ID
//uint8_t receive_data[28] = {0};
/**
*\*\name CAN_CONFIG
*\*\fun CAN configure.
*\*\param none
*\*\return none
**/
void CAN_CONFIG(void)
{
RCC_APB1_Peripheral_Clock_Enable(RCC_APB1_PERIPH_CAN);
/* Initializes CAN*/
CAN_NVIC_Configuration();
CAN_GPIO_Configuration();
CAN_Reset(CAN);
CAN_Structure_Initializes(&CAN_InitStructure);
/* CAN cell init */
CAN_InitStructure.TTCM = DISABLE;
CAN_InitStructure.ABOM = ENABLE;
CAN_InitStructure.AWKUM = ENABLE;
CAN_InitStructure.NART = DISABLE;
CAN_InitStructure.RFLM = DISABLE;
CAN_InitStructure.TXFP = ENABLE;
CAN_InitStructure.OperatingMode = CAN_NORMAL_MODE;
CAN_InitStructure.RSJW = CAN_RSJW_1TQ;
CAN_InitStructure.TBS1 = CAN_TBS1_8TQ;
CAN_InitStructure.TBS2 = CAN_TBS2_7TQ;
CAN_InitStructure.BaudRatePrescaler = 4;
/*Initializes the CAN */
CAN_Initializes(CAN, &CAN_InitStructure);
/* CAN filter init */
CAN_FilterInitStructure.Filter_Num = 0;
CAN_FilterInitStructure.Filter_Mode = CAN_FILTER_IDMASKMODE;
CAN_FilterInitStructure.Filter_Scale = CAN_FILTER_32BITSCALE;
CAN_FilterInitStructure.Filter_HighId = 0;
CAN_FilterInitStructure.Filter_LowId = 0;
CAN_FilterInitStructure.FilterMask_HighId = 0;
CAN_FilterInitStructure.FilterMask_LowId = 0;
CAN_FilterInitStructure.Filter_FIFOAssignment = CAN_FIFO0;
CAN_FilterInitStructure.Filter_Act = ENABLE;
CAN_Filter_Initializes(&CAN_FilterInitStructure);
/* IT Configuration for CAN */
CAN_Config_Interrupt_Enable(CAN, CAN_INT_FMP0);
}
/**
*\*\name CAN_NVIC_Configuration
*\*\fun CAN NVIC configure.
*\*\param none
*\*\return none
**/
void CAN_NVIC_Configuration(void)
{
NVIC_InitType NVIC_InitStructure;
/* Initializes the NVIC */
NVIC_Initializes(&NVIC_InitStructure);
/* NVIC configure */
NVIC_InitStructure.NVIC_IRQChannel = CAN_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Initializes(&NVIC_InitStructure);
}
/**
*\*\name CAN_GPIO_Configuration
*\*\fun CAN GPIO configure.
*\*\param none
*\*\return none
**/
void CAN_GPIO_Configuration(void)
{
GPIO_InitType GPIO_InitStructure;
/* Initializes the GPIO */
GPIO_Structure_Initialize(&GPIO_InitStructure);
/* configure CAN pin */
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
GPIO_InitStructure.Pin = GPIO_PIN_8;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.GPIO_Alternate = GPIO_AF6_CAN;
GPIO_Peripheral_Initialize(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitStructure.GPIO_Alternate = GPIO_AF6_CAN;
GPIO_Peripheral_Initialize(GPIOB, &GPIO_InitStructure);
}
//----------------------------------------------------------
// static const uint8_t crc8_table[256] =
// {
// 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
// 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
// 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
// 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
// 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
// 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
// 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
// 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
// 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
// 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
// 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
// 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
// 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
// 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
// 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
// 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3};
// // 数据中包含 1 字节校验 //
// uint8_t crc8_check(uint8_t *data, uint16_t len)
// {
// uint16_t i = 0;
// uint8_t fcs = 0x0;
// // 计算数据校验
// for (i = 0; i < len; i++)
// {
// fcs = crc8_table[(uint8_t)fcs ^ *data];
// data++;
// }
// return fcs;
// }
/**
* @brief 发送 开始升级 命令
*
* @param can_id
* @param data 2个字节数据
*/
void C_Send_Start_Update_Message(uint8_t can_id, uint8_t device_id)
{
uint8_t func_code = C_UPDATE_TYPE_FUN_CODE_WRITE; // 功能码:写入 0x90 ,读取0x91
uint8_t fun_ext_code = C_UPDATE_TYPE_FUN_EXT_CODE_START_UPDATE; // 功能扩展码: 0x00
uint8_t data[2] = {0x90, 0x09};
C_Send_Frame_Data(can_id, device_id, func_code, fun_ext_code, 2, data);
}
/**
* @brief 发送 快速升级(预留) 命令:改变波特率
*
* @param can_id
* @param data 2个字节数据
*/
void C_Send_Fast_Update_Message(uint8_t can_id, uint8_t device_id)
{
uint8_t func_code = C_UPDATE_TYPE_FUN_CODE_WRITE; // 功能码:写入 0x90 ,读取0x91
uint8_t fun_ext_code = C_UPDATE_TYPE_FUN_EXT_CODE_FAST_UPDATE; // 功能扩展码: 0x02
uint8_t data[2] = {0x92, 0x29};
C_Send_Frame_Data(can_id, device_id, func_code, fun_ext_code, 2, data);
}
/**
* @brief 发送 准备升级 命令,擦除APP Flash区域,同时将APP信息存FLASH Boot信息区域
*
* @param can_id
* @param device_id 设备ID
* @param crc16 app数据的crc16
* @param app_data_pack_total_num app数据的总包数
* @param project_id 项目ID
*/
void C_Send_Ready_Update_Message(uint8_t can_id, uint8_t device_id, uint16_t app_data_crc16, uint16_t app_data_pack_total_num, uint32_t project_id)
{
uint8_t func_code = C_UPDATE_TYPE_FUN_CODE_WRITE; // 功能码:写入 0x90 ,读取0x91
uint8_t fun_ext_code = C_UPDATE_TYPE_FUN_EXT_CODE_READY_UPDATE; // 功能扩展码: 0x04
uint8_t data[8] = {0};
data[0] = app_data_crc16 & 0xFF; // crc16 低8位
data[1] = app_data_crc16 >> 8; // crc16高8位
data[2] = app_data_pack_total_num & 0xFF; // app_data_pack_total_num 低8位
data[3] = (app_data_pack_total_num >> 8) & 0xFF; // app_data_pack_total_num 高8位
data[4] = project_id & 0xFF; // project_id bit0-bit7
data[5] = (project_id >> 8) & 0xFF; // project_id bit8-bit15
data[6] = (project_id >> 16) & 0xFF; // project_id bit16-bit7
data[7] = (project_id >> 24) & 0xFF; // project_id bit24-bit32
C_Send_Frame_Data(can_id, device_id, func_code, fun_ext_code, 8, data);
}
/**
* @brief 发送 APP数据包
*
* @param can_id
* @param device_id 设备ID
* @param app_data_num APP数据包序号,从0开始,0表示第一包
* @param data 128个字节APP数据
*/
void C_Send_Update_Data_Message(uint8_t can_id, uint8_t device_id, uint16_t app_data_num, uint8_t *data)
{
uint8_t data_length = 131; //(2字节数据分包序号+128个字节数据+当前包的固件数据的CRC8)
uint8_t func_code = C_UPDATE_TYPE_FUN_CODE_WRITE; // 功能码:写入 0x90 ,读取0x91
uint8_t fun_ext_code = C_UPDATE_TYPE_FUN_EXT_CODE_UPDATE_DATA; // 功能扩展码: 0x1C
uint8_t *new_data = (uint8_t *)malloc(data_length); //
new_data[0] = app_data_num & 0xFF; // 数据包序号 app_data_num 低8位
new_data[1] = (app_data_num >> 8) & 0xFF; // 数据包序号 app_data_num 高8位
memcpy(new_data + 2, data, 128); // 128 字节数据
new_data[data_length - 1] = crc8_check(new_data + 2, 128); // 128个字节数据的CRC
C_Send_Frame_Data(can_id, device_id, func_code, fun_ext_code, data_length, new_data);
free(new_data); // 释放内存
}
/**
* @brief 升级完成,
*
* @param can_id
* @param device_id 设备ID
* @param data 2个字节数据
*/
void C_Send_Finish_Update_Message(uint8_t can_id, uint8_t device_id)
{
uint8_t func_code = C_UPDATE_TYPE_FUN_CODE_WRITE; // 功能码:写入 0x90 ,读取0x91
uint8_t fun_ext_code = C_UPDATE_TYPE_FUN_EXT_CODE_FINISH_UPDATE; // 功能扩展码: 0x8E
uint8_t data[2] = {0x8E, 0xE8};
C_Send_Frame_Data(can_id, device_id, func_code, fun_ext_code, 2, data);
}
/**
* @brief CAN发送一帧数据,(即 识别码|功能码|功能扩展码|数据长度|数据|校验码 格式)
*
* @param can_id CAN ID
* @param device_id 设备码
* @param func_code 功能码
* @param fun_ext_code 功能扩展码
* @param data_length data_length 数据长度(最大为0xFF)
* @param data 数据 (数据长度最长只能是255个,0xFF)
*/
void C_Send_Frame_Data(uint16_t can_id, uint8_t device_id, uint8_t func_code, uint8_t fun_ext_code, uint8_t data_length, uint8_t *data)
{
// 一共要发送多少个CAN包
uint16_t number_of_packs = (data_length + 3)%6 ? (data_length + 3)/6+1 : (data_length + 3)/6; // 每包数据都包括了识别ID和功能码,所以传输的有效数据从扩展码开始计算,每包传输有效数据是6个字节;data_length+3:表示n个数据+1字节功能扩展码+1字节长度+1字节校验码
// uint16_t number_of_packs = ceil((double)(data_length + 3) / 6); // 每包数据都包括了识别ID和功能码,所以传输的有效数据从扩展码开始计算,每包传输有效数据是6个字节;data_length+3:表示n个数据+1字节功能扩展码+1字节长度+1字节校验码
// 存储整个帧数据
uint8_t *frame = (uint8_t *)malloc((size_t)(2 + number_of_packs * 6)); // 申请一组数据的空间大小,用于存储数据
// 设备id只使用bit5-bit0
device_id = device_id & 0x3F;
// 填充整个帧数据
frame[0] = 0; // 识别id,暂不赋予有效的值
frame[1] = func_code; // 功能码
frame[2] = fun_ext_code; // 功能扩展码
frame[3] = data_length; // 数据长度
memcpy(frame + 4, data, data_length); // 数据
frame[4 + data_length] = crc8_check(frame + 1, data_length + 3); // 校验内容为从功能码到数据域所有数据的CRC8校验
// 一帧数据分多个CAN包发送
for (int i = 0; i < number_of_packs; i++)
{
uint8_t check_id = 0; // 识别ID
// 单包
if (number_of_packs == 1)
{
check_id = PACK_TYPE_SINGLE | device_id;
}
else // 多包
{
if (i == 0) // 起始包
{
check_id = PACK_TYPE_START | device_id;
}
else if (i == number_of_packs - 1) // 结束包
{
check_id = PACK_TYPE_END | device_id;
}
else // 续传包
{
check_id = PACK_TYPE_CONTINUE | device_id;
}
}
// 填充一个CAN包的数据
uint8_t *can_data = frame + i * 6;
can_data[0] = check_id;
can_data[1] = func_code;
// 发送一个CAN包
Send_CAN_Pack_Message(can_id, can_data);
SysTick_Delay_Ms(1);
}
// 帧数据使用完成,释放申请的动态内存
free(frame);
}
/**
* @brief 发送一个CAN包
*
* @param can_id CAN-ID
* @param data 包含数据的8个字节的数组
*/
void Send_CAN_Pack_Message(uint16_t can_id, uint8_t data[8])
{
/* Transmit assign */
CAN_TxMessage.StdId = can_id;
CAN_TxMessage.ExtId = 0x00;
CAN_TxMessage.IDE = CAN_STANDARD_ID; /* CAN_ID_STD / CAN_ID_EXT */
CAN_TxMessage.RTR = CAN_RTRQ_DATA; /* CAN_RTR_DATA / CAN_RTR_REMOTE */
CAN_TxMessage.DLC = 8; // 发送长度为8字节
memcpy(CAN_TxMessage.Data, data, 8);
CAN_Transmit_Message_initializes(CAN, &CAN_TxMessage);
}
key.c
#include "key.h"
#include "main.h"
void KeyInputExtiInit(GPIO_Module* GPIOx, uint16_t Pin)
{
GPIO_InitType GPIO_InitStructure;
EXTI_InitType EXTI_InitStructure;
NVIC_InitType NVIC_InitStructure;
/* Enable the GPIO Clock */
if (GPIOx == GPIOA)
{
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
}
else if (GPIOx == GPIOB)
{
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
}
else if (GPIOx == GPIOC)
{
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOC);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
}
else if (GPIOx == GPIOD)
{
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOD);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
}
else
{
return;
}
if (Pin <= GPIO_PIN_ALL)
{
GPIO_Structure_Initialize(&GPIO_InitStructure);
GPIO_InitStructure.Pin = Pin;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
GPIO_Peripheral_Initialize(GPIOx, &GPIO_InitStructure);
}
/* Configure key EXTI Line to key input Pin */
if(Pin == GPIO_PIN_6)
{
GPIO_EXTI_Line_Set(KEY_INPUT_PORT_SOURCE_C, KEY_INPUT_PIN_SOURCE_C);
EXTI_InitStructure.EXTI_Line = KEY_INPUT_EXTI_LINE_C;
}
if(Pin == GPIO_PIN_5)
{
GPIO_EXTI_Line_Set(KEY_INPUT_PORT_SOURCE_U, KEY_INPUT_PIN_SOURCE_U);
EXTI_InitStructure.EXTI_Line = KEY_INPUT_EXTI_LINE_U;
}
/* Configure key EXTI line */
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Peripheral_Initializes(&EXTI_InitStructure);
/* Set key input interrupt priority */
NVIC_InitStructure.NVIC_IRQChannel = KEY_INPUT_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_SUB_PRIORITY_1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Initializes(&NVIC_InitStructure);
}
led.c
#include "led.h"
#include "main.h"
void LedInit(void)
{
//RCC
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA | RCC_AHB_PERIPH_GPIOB | RCC_AHB_PERIPH_GPIOC | RCC_AHB_PERIPH_GPIOD);
RCC_APB1_Peripheral_Clock_Enable(RCC_APB1_PERIPH_TIM2);
RCC_APB1_Peripheral_Clock_Enable(RCC_APB1_PERIPH_TIM3);
//LED_GREEN GPIO
GPIO_InitType GPIO_InitStructure;
GPIO_Structure_Initialize(&GPIO_InitStructure);
GPIO_InitStructure.Pin = LED_GREEN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_Peripheral_Initialize(LED_GREEN_PORT, &GPIO_InitStructure);
//配置PWM GPIO引脚
Led_PWM_GPIO_Initialize();
// 配置定时器
// uint32_t tim_clk=0;
// RCC_ClocksType RCC_Clocks;
// RCC_Clocks_Frequencies_Value_Get(&RCC_Clocks);
// if(RCC_Clocks.HclkFreq > RCC_Clocks.Pclk2Freq)
// {
// tim_clk = RCC_Clocks.Pclk2Freq *2;
// }
// else
// {
// tim_clk = RCC_Clocks.Pclk2Freq;
// }
Led_PWM_TIM_Base_Initialize(TIM2, 5000, 12800);
Led_PWM_TIM_Base_Initialize(TIM3, 5000, 12800);
// 配置PWM通道
Led_PWM_Config();
}
void Led_PWM_GPIO_Initialize(void)
{
GPIO_InitType GPIO_InitStructure;
GPIO_Structure_Initialize(&GPIO_InitStructure);
GPIO_InitStructure.Pin = LED_RED_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
GPIO_InitStructure.GPIO_Alternate = LED_RED_TIM2_CH2_AF;
GPIO_Peripheral_Initialize(LED_RED_PORT, &GPIO_InitStructure);
GPIO_InitStructure.Pin = LED_BLUE_PIN;
GPIO_InitStructure.GPIO_Alternate = LED_BLUE_TIM3_CH2_AF;
GPIO_Peripheral_Initialize(LED_BLUE_PORT, &GPIO_InitStructure);
}
void Led_PWM_TIM_Base_Initialize(TIM_Module *TIMx,uint16_t period,uint16_t prescaler)
{
TIM_TimeBaseInitType TIM_TimeBaseStructure;
TIM_Base_Struct_Initialize(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.Period=period;
TIM_TimeBaseStructure.Prescaler=prescaler;
TIM_TimeBaseStructure.ClkDiv=0;
TIM_TimeBaseStructure.CntMode=TIM_CNT_MODE_UP;
TIM_Base_Initialize(TIMx,&TIM_TimeBaseStructure);
}
void Led_PWM_Config(void)
{
OCInitType TIM_OCInitStructure;
TIM_Output_Channel_Struct_Initialize(&TIM_OCInitStructure);
/* Channel 1, 2 and 3 Configuration in PWM mode */
TIM_OCInitStructure.OcMode = TIM_OCMODE_PWM2;
TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
TIM_OCInitStructure.OutputNState = TIM_OUTPUT_NSTATE_DISABLE;
TIM_OCInitStructure.Pulse = 0; //设置占空比
TIM_OCInitStructure.OcPolarity = TIM_OC_POLARITY_LOW;
TIM_OCInitStructure.OcNPolarity = TIM_OCN_POLARITY_LOW;
TIM_OCInitStructure.OcIdleState = TIM_OC_IDLE_STATE_SET;
TIM_OCInitStructure.OcNIdleState = TIM_OCN_IDLE_STATE_RESET;
TIM_Output_Channel2_Initialize(TIM2, &TIM_OCInitStructure);
TIM_Output_Channel2_Initialize(TIM3, &TIM_OCInitStructure);
TIM_On(TIM2);
TIM_On(TIM3);
TIM_PWM_Output_Enable(TIM2);
TIM_PWM_Output_Enable(TIM3);
}
void LED(LED_STATE led_status)
{
switch(led_status)
{
case LED_UPDATE_START :
TIM_Compare2_Set(TIM3,2500); //蓝 闪
TIM_Compare2_Set(TIM2,0); //红 灭
// LedOff(LED_GREEN_PORT, LED_GREEN_PIN);//绿 灭
break;
case LED_UPDATE_SUCCEED :
LedOn(LED_GREEN_PORT, LED_GREEN_PIN); //绿 亮
TIM_Compare2_Set(TIM3,0); //蓝 灭
TIM_Compare2_Set(TIM2,0); //红 灭
break;
case LED_UPDATE_KEY_FINISH : //手动退出流程,且流程失败,红灯常亮
TIM_Compare2_Set(TIM2,5000); //红 亮
TIM_Compare2_Set(TIM3,0); //蓝 灭
// LedOff(LED_GREEN_PORT, LED_GREEN_PIN);//绿 亮
break;
case LED_UPDATE_FAIL :
TIM_Compare2_Set(TIM2,2500); //红 闪
break;
default :
break;
}
}
void LedOn(GPIO_Module *GPIOx, uint16_t Pin)
{
GPIO_Pins_Set(GPIOx, Pin);
}
void LedOff(GPIO_Module *GPIOx, uint16_t Pin)
{
GPIO_PBC_Pins_Reset(GPIOx, Pin);
}
time.c
#include "time.h"
#include "main.h"
/**
* @brief Configure the system tick clock.
*/
uint32_t SysTick_InitConfig(uint32_t ms)
{
uint32_t ticks=0;
u8 pre=8;//分频
RCC_ClocksType RCC_Clocks={0};
if(ms==0)
{
return(1);
}
//UartReTimer();
RCC_Clocks_Frequencies_Value_Get(&RCC_Clocks);
ticks=RCC_Clocks.SysclkFreq / pre/1000*ms;
if (ticks > SysTick_LOAD_RELOAD_Msk)
return (1); /* Reload value impossible */
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */
SysTick->VAL = 0; /* Load the SysTick Counter Value */
SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
return (0); /* Function successful */
}
/**
* @brief Use the system tick clock to delay.
*/
void SysTick_Delay_Ms(uint32_t ms)
{
uint32_t i=0;
SysTick->VAL = 0; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_ENABLE_Msk ;
for (i = 0; i < ms; i++)
{
/* When the value of the counter is reduced to 0, the bit 16 of the CRTL register is set to 1.
When set to 1, the bit will cleared to 0 with read
*/
while (!((SysTick->CTRL) & (1 << 16)))
;
}
// Disable SysTick timer
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
common.c
#include "common.h"
#include "main.h"
#include <string.h>
static const uint8_t crc8_table[256] =
{
0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3};
// 数据中包含 1 字节校验 //
uint8_t crc8_check(uint8_t *data, uint16_t len)
{
uint16_t i = 0;
uint8_t fcs = 0x0;
// 计算数据校验
for (i = 0; i < len; i++)
{
fcs = crc8_table[(uint8_t)fcs ^ *data];
data++;
}
return fcs;
}
u_app_data.c
#include "u_app_data.h"
#include "main.h"
#include "uart.h"
#include "common.h"
#include <string.h>
extern uint8_t TxMark[COMNUM],RxMark[COMNUM];
extern uint8_t UartReadBuf[9];
extern uint16_t ReceiveLen[COMNUM];
// extern uint8_t UartReadBuf[COMNUM][UARTRESIZE];
U_UPDATE_STATE u_g_update_state = U_UPDATE_START; // 初始状态
uint8_t u_app_data_buffer[128] = {0}; // 存储读到的128个字节的数据
void UART_Request_Update_Flow(void)
{
uint8_t update_finish = 0; // 标志位:1升级结束,退出流程
u_g_update_state = U_UPDATE_START; // 初始状态
uint16_t u_app_pack_num = 0; // APP 数据包序号
uint16_t time = 0;
while (1)
{
if (update_finish == 1)
break; // 标志位:1升级结束,退出流程
if (g_key_on == 0)//按键手动退出流程
{
// if(update_finish != 1)
// {
// LED(LED_UPDATE_KEY_FINISH); // 退出流程时,未成功则红灯常亮
// }
break; // 在一直错误,升级失败的时候,通过按键退出流程,
}
switch (u_g_update_state)
{
case U_UPDATE_START:
U_Send_Start_Update_Message(UART3_ID, U_DEVICE_ID); // 开始升级
while (RxMark[0] == UNVALID_MARK && time < 300)
{
SysTick_Delay_Ms(10); // 等待接收完成
time++;
; // 等待接收完成 或 手动退出流程
}
if (U_Get_Sending_UpdateStart_Result(UartReadBuf) == SENGDING_OK) // 判断响应信息,响应为OK
{
U_Send_Start_Update_Message(UART3_ID, U_DEVICE_ID); // 开始升级
while (RxMark[0] == UNVALID_MARK && time < 300)
{
SysTick_Delay_Ms(10); // 等待接收完成
time++;
; // 等待接收完成 或 手动退出流程
}
if (U_Get_Sending_UpdateStart_Result(UartReadBuf) == SENGDING_OK) // 判断响应信息,响应为OK
{
u_g_update_state = U_UPDATE_READY; // 更改更新程序流程状态为 U_UPDATE_READY
}
else
{
u_g_update_state = U_UPDATE_FAIL; // 响应信息,响应为FAIL,更改更新程序流程状态为 U_UPDATE_FAIL
}
}
else
{
u_g_update_state = U_UPDATE_FAIL; // 响应信息,响应为FAIL,更改更新程序流程状态为 U_UPDATE_FAIL
}
break;
case U_UPDATE_READY:
U_Send_Ready_Update_Message(UART3_ID, U_DEVICE_ID, U_Get_APPCodeCrc(), U_Get_APPCodeTotalNum(), U_PROJECT_ID); // 准备升级,ceil(Get_APPCodeLen()/128,数据的总包数
while (RxMark[0] == UNVALID_MARK && time < 300)
{
SysTick_Delay_Ms(10); // 等待接收完成
time++;
; // 等待接收完成 或 手动退出流程
}
if (U_Get_Sending_UpdateReady_Result(UartReadBuf) == SENGDING_OK) // 判断响应信息,响应为OK
{
u_g_update_state = U_UPDATE_DATA; // 更改更新程序流程状态为 U_UPDATE_DATA
}
else
{
u_g_update_state = U_UPDATE_FAIL; // 响应信息,响应为FAIL,更改更新程序流程状态为 U_UPDATE_FAIL
}
// ReceiveLen[0] = 0;
break;
case U_UPDATE_DATA:
U_Read_App_Data(U_APP_CODE_ADDR_SART + u_app_pack_num * 128, u_app_data_buffer); // 读取128个数据到u_app_data_buffer
U_Send_Update_Data_Message(UART3_ID, U_DEVICE_ID, u_app_pack_num, u_app_data_buffer); // 发送app区数据
while (RxMark[0] == UNVALID_MARK && time < 300)
{
SysTick_Delay_Ms(10); // 等待接收完成
time++;
; // 等待接收完成 或 手动退出流程
}
if (U_Get_Sending_UpdateData_Result(UartReadBuf) == SENGDING_OK) // 判断响应信息,响应为OK
{
u_g_update_state = U_UPDATE_DATA; // 更改更新程序流程状态为 U_UPDATE_DATA
if ((u_app_pack_num + 1) >= U_Get_APPCodeTotalNum()) // 若是最后一帧APP数据,更新程序流程状态为 U_UPDATE_FINISH
{
u_g_update_state = U_UPDATE_FINISH; // 更改更新程序流程状态为 U_UPDATE_FINISH
}
u_app_pack_num++; // 成功,则发下一帧 APP数据
}
else
{
u_g_update_state = U_UPDATE_FAIL; // 响应信息,响应为FAIL,更改更新程序流程状态为 U_UPDATE_FAIL
}
// ReceiveLen[0] = 0;
break;
case U_UPDATE_FINISH:
U_Send_Finish_Update_Message(UART3_ID, U_DEVICE_ID); // 升级结束
while (RxMark[0] == UNVALID_MARK && time < 300)
{
SysTick_Delay_Ms(10); // 等待接收完成
time++;
; // 等待接收完成 或 手动退出流程
}
if (U_Get_Sending_UpdateFinish_Result(UartReadBuf) == SENGDING_OK) // 判断响应信息,响应为OK
{
u_g_update_state = U_UPDATE_SUCCEED; // 更改更新程序流程状态为 U_UPDATE_SUCCEED
}
else
{
u_g_update_state = U_UPDATE_FAIL; // 响应信息,响应为FAIL,更改更新程序流程状态为 U_UPDATE_FAIL
}
// ReceiveLen[0] = 0;
break;
case U_UPDATE_SUCCEED:
update_finish = 1; //标志位:1升级结束,退出流程
//LED(LED_UPDATE_SUCCEED); // 成功 绿灯
//LedOn(LED_GREEN_PORT, LED_GREEN_PIN); //绿 亮
//TIM_Compare2_Set(TIM3,0); //蓝 灭
//TIM_Compare2_Set(TIM2,0); //红 灭
break;
case U_UPDATE_FAIL:
update_finish = 1; // 失败则退出流程,重新按键开始
//u_app_pack_num = 0; // 失败,则重新执行流程,所有数据重新发送
// LED(LED_UPDATE_FAIL); // 失败 红灯闪
TIM_Compare2_Set(TIM2,2500); //红 闪
break;
default:
break;
}
RxMark[0] = UNVALID_MARK; // 重新接收数据
time = 0;
}
}
/**
* @brief 获取 U_UPDATE_START流程的响应结果
*
* @param data
* @return SENDING_RESULT
*/
SENDING_RESULT U_Get_Sending_UpdateStart_Result(uint8_t *data)
{
return U_Get_Sending_Result(UartReadBuf, U_UPDATE_TYPE_FUN_CODE_WRITE, U_UPDATE_TYPE_FUN_EXT_CODE_START_UPDATE); // 判断响应信息,响应为OK
}
/**
* @brief 获取 U_UPDATE_READY 流程的响应结果
*
* @param data
* @return SENDING_RESULT
*/
SENDING_RESULT U_Get_Sending_UpdateReady_Result(uint8_t *data)
{
return U_Get_Sending_Result(UartReadBuf, U_UPDATE_TYPE_FUN_CODE_WRITE, U_UPDATE_TYPE_FUN_EXT_CODE_READY_UPDATE); // 判断响应信息,响应为OK
}
/**
* @brief 获取 UPDATE_DATA流程的响应结果
*
* @param data
* @return SENDING_RESULT
*/
SENDING_RESULT U_Get_Sending_UpdateData_Result(uint8_t *data)
{
return U_Get_Sending_Result(UartReadBuf, U_UPDATE_TYPE_FUN_CODE_WRITE, U_UPDATE_TYPE_FUN_EXT_CODE_UPDATE_DATA); // 判断响应信息,响应为OK
}
/**
* @brief 获取 U_UPDATE_FINISH 流程的响应结果
*
* @param data
* @return SENDING_RESULT
*/
SENDING_RESULT U_Get_Sending_UpdateFinish_Result(uint8_t *data)
{
return U_Get_Sending_Result(UartReadBuf, U_UPDATE_TYPE_FUN_CODE_WRITE, U_UPDATE_TYPE_FUN_EXT_CODE_FINISH_UPDATE); // 判断响应信息,响应为OK
}
/**
* @brief 获取发送后的成功或失败的结果
*
* @param data 接收到的响应的数据
* @return uint8_t
*/
SENDING_RESULT U_Get_Sending_Result(uint8_t *data, uint8_t fun_code, uint8_t fun_ext_code)
{
uint8_t fun_code_ask = UartReadBuf[3]; // 功能码
uint8_t fun_ext_code_ask = UartReadBuf[4]; // 功能扩展码
uint8_t data_ask = UartReadBuf[6]; // 数据
uint8_t crc = crc8_check(UartReadBuf + 1, 6); // 计算响应信息的CRC,CRC8校验内容为从功能码到数据域所有数据的CRC8校验
if ((crc == UartReadBuf[7]) && (UartReadBuf[0]==0xF2) && (UartReadBuf[8]==0xF1)) // 计算的CRC与响应数据中的CRC结果一致,帧头帧尾一致
{
if ((data_ask == 0) && (fun_code_ask == fun_code) && (fun_ext_code_ask == fun_ext_code)) // 回复的数据是0,表示成功;校验响应的数据中的功能码和扩展码
{
return SENGDING_OK;
}
else
{
return SENDING_FAIL;
}
}
else
{
return SENDING_FAIL;
}
}
/**
* @brief 读取APP数据的CRC值
*
* @return uint16_t
*/
uint16_t U_Get_APPCodeCrc(void)
{
return *(uint16_t *)U_APP_CODE_CRC_ADDR;
}
///**
// * @brief 读取APP数据的CRC值
// *
// * @return uint16_t
// */
//uint16_t Get_FlashAPPCodeCrc(void)
//{
// uint16_t crc=0;
num=*(uint16_t *)U_APP_CODE_PACK_TOTAL_NUM_ADDR;
// crc=CRC16((unsigned char *)U_APP_CODE_ADDR_SART,4096);
// return crc;
//}
/**
* @brief 读取APP数据的总包数
*
* @return uint16_t
*/
uint16_t U_Get_APPCodeTotalNum(void)
{
uint16_t num=0;
num=*(uint16_t *)U_APP_CODE_PACK_TOTAL_NUM_ADDR;
return num;
}
/**
* @brief 从Flash地址读取128个字节的APP数据
*
* @param flash_address
* @param data_buffer
*/
void U_Read_App_Data(uint32_t flash_address, uint8_t *data_buffer)
{
for (uint8_t i = 0; i < 128; i++) // 只读取128字节的数据
{
data_buffer[i] = *((uint8_t *)(flash_address + i));
}
}
void U_Load_App(u32 appxaddr)
{
__disable_irq(); // 关闭所有中断
// uint8_t i;
if (((*(volatile uint32_t *)appxaddr) & 0x2FFE0000) == 0x20000000) // 检查栈顶地址是否合法.0x20000000是sram的起始地址,也是程序的栈顶地址
{
// 定义一个函数指针,指向应用程序的起始地址
void (*JumpToApp)(void) = (void (*)(void))(*((uint32_t *)(appxaddr + 4))); // 用户代码区第二个字为程序开始地址(复位地址)
__set_MSP(*(volatile uint32_t *)appxaddr);
JumpToApp(); // 跳转到APP.
}
}
c_app_data.c
在这里插入代码片#include "c_app_data.h"
#include "main.h"
#include "can.h"
#include "common.h"
C_UPDATE_STATE c_g_update_state = C_UPDATE_START; // 初始状态
uint8_t c_app_data_buffer[128] = {0}; // 存储读到的128个字节的数据
void CAN_Request_Update_Flow(void)
{
uint8_t update_finish = 0; // 标志位:1升级结束,退出流程
c_g_update_state = C_UPDATE_START; // 初始状态
uint16_t c_app_pack_num = 0; // APP 数据包序号
while (1)
{
if (update_finish == 1)
break; // 标志位:1升级结束,退出流程
if (g_key_on == 0)//按键手动退出流程
{
// if(C_UPDATE_FINISH != 1)
// {
// LED(LED_UPDATE_KEY_FINISH); // 退出流程时,未成功则红灯常亮
// }
break; // 在一直错误,升级失败的时候,通过按键退出流程,
}
switch (c_g_update_state)
{
case C_UPDATE_START:
C_Send_Start_Update_Message(CAN_ID, C_DEVICE_ID); // 开始升级
while (g_rx_flag == UNRECEIVED && g_key_on == 1)
; // 等待接收完成 或 手动退出流程
if (C_Get_Sending_UpdateStart_Result(CAN_RxMessage.Data) == SENGDING_OK) // 判断响应信息,响应为OK
{
c_g_update_state = C_UPDATE_READY; // 更改更新程序流程状态为 C_UPDATE_READY
}
else
{
c_g_update_state = C_UPDATE_FAIL; // 响应信息,响应为FAIL,更改更新程序流程状态为 C_UPDATE_FAIL
}
break;
case C_UPDATE_READY:
C_Send_Ready_Update_Message(CAN_ID, C_DEVICE_ID, C_Get_APPCodeCrc(), C_Get_APPCodeTotalNum(), C_PROJECT_ID); // 准备升级,ceil(Get_APPCodeLen()/128,数据的总包数
while (g_rx_flag == UNRECEIVED && g_key_on == 1)
; // 等待接收完成 或 手动退出流程
if (C_Get_Sending_UpdateReady_Result(CAN_RxMessage.Data) == SENGDING_OK) // 判断响应信息,响应为OK
{
c_g_update_state = C_UPDATE_DATA; // 更改更新程序流程状态为 C_UPDATE_DATA
}
else
{
c_g_update_state = C_UPDATE_FAIL; // 响应信息,响应为FAIL,更改更新程序流程状态为 C_UPDATE_FAIL
}
break;
case C_UPDATE_DATA:
C_Read_App_Data(C_APP_CODE_ADDR_SART + c_app_pack_num * 128, c_app_data_buffer); // 读取128个数据到c_app_data_buffer
C_Send_Update_Data_Message(CAN_ID, C_DEVICE_ID, c_app_pack_num, c_app_data_buffer); // 发送app区数据
while (g_rx_flag == UNRECEIVED && g_key_on == 1)
; // 等待接收完成 或 手动退出流程
if (C_Get_Sending_UpdateData_Result(CAN_RxMessage.Data) == SENGDING_OK) // 判断响应信息,响应为OK
{
c_g_update_state = C_UPDATE_DATA; // 更改更新程序流程状态为 C_UPDATE_DATA
if ((c_app_pack_num + 1) >= C_Get_APPCodeTotalNum()) // 若是最后一帧APP数据,更新程序流程状态为 C_UPDATE_FINISH
{
c_g_update_state = C_UPDATE_FINISH; // 更改更新程序流程状态为 C_UPDATE_DATA
}
c_app_pack_num++; // 成功,则发下一帧 APP数据
}
else
{
c_g_update_state = C_UPDATE_FAIL; // 响应信息,响应为FAIL,更改更新程序流程状态为 C_UPDATE_FAIL
}
break;
case C_UPDATE_FINISH:
C_Send_Finish_Update_Message(CAN_ID, C_DEVICE_ID); // 升级结束
while(g_rx_flag == UNRECEIVED && g_key_on == 1)
; // 等待接收完成 或 手动退出流程
if (C_Get_Sending_UpdateFinish_Result(CAN_RxMessage.Data) == SENGDING_OK) // 判断响应信息,响应为OK
{
c_g_update_state = C_UPDATE_SUCCEED; // 更改更新程序流程状态为 C_UPDATE_SUCCEED
}
else
{
c_g_update_state = C_UPDATE_FAIL; // 响应信息,响应为FAIL,更改更新程序流程状态为 C_UPDATE_FAIL
}
break;
case C_UPDATE_SUCCEED:
update_finish = 1; //标志位:1升级结束,退出流程
// LED(LED_C_UPDATE_SUCCEED); // 成功 绿灯
LedOn(LED_GREEN_PORT, LED_GREEN_PIN); //绿 亮
// TIM_Compare2_Set(TIM3,0); //蓝 灭
// TIM_Compare2_Set(TIM2,0); //红 灭
break;
case C_UPDATE_FAIL:
c_g_update_state = C_UPDATE_START; // 所有响应失败都不做处理,直接重新开始
c_app_pack_num = 0; // 失败,则重新执行流程,所有数据重新发送
// LED(LED_C_UPDATE_FAIL); // 失败 红灯闪
TIM_Compare2_Set(TIM2,2500); //红 闪
break;
default:
break;
}
g_rx_flag = UNRECEIVED; // g_rx_flag更改为UNRECEIVED
}
}
/**
* @brief 获取 C_UPDATE_START流程的响应结果
*
* @param data
* @return SENDING_RESULT
*/
SENDING_RESULT C_Get_Sending_UpdateStart_Result(uint8_t *data)
{
return C_Get_Sending_Result(data, C_UPDATE_TYPE_FUN_CODE_WRITE, C_UPDATE_TYPE_FUN_EXT_CODE_START_UPDATE); // 判断响应信息,响应为OK
}
/**
* @brief 获取 C_UPDATE_READY 流程的响应结果
*
* @param data
* @return SENDING_RESULT
*/
SENDING_RESULT C_Get_Sending_UpdateReady_Result(uint8_t *data)
{
return C_Get_Sending_Result(CAN_RxMessage.Data, C_UPDATE_TYPE_FUN_CODE_WRITE, C_UPDATE_TYPE_FUN_EXT_CODE_READY_UPDATE); // 判断响应信息,响应为OK
}
/**
* @brief 获取 C_UPDATE_DATA流程的响应结果
*
* @param data
* @return SENDING_RESULT
*/
SENDING_RESULT C_Get_Sending_UpdateData_Result(uint8_t *data)
{
return C_Get_Sending_Result(CAN_RxMessage.Data, C_UPDATE_TYPE_FUN_CODE_WRITE, C_UPDATE_TYPE_FUN_EXT_CODE_UPDATE_DATA); // 判断响应信息,响应为OK
}
/**
* @brief 获取 C_UPDATE_FINISH 流程的响应结果
*
* @param data
* @return SENDING_RESULT
*/
SENDING_RESULT C_Get_Sending_UpdateFinish_Result(uint8_t *data)
{
return C_Get_Sending_Result(CAN_RxMessage.Data, C_UPDATE_TYPE_FUN_CODE_WRITE, C_UPDATE_TYPE_FUN_EXT_CODE_FINISH_UPDATE); // 判断响应信息,响应为OK
}
/**
* @brief 获取发送后的成功或失败的结果
*
* @param data 接收到的响应的数据
* @return uint8_t
*/
SENDING_RESULT C_Get_Sending_Result(uint8_t *data, uint8_t fun_code, uint8_t fun_ext_code)
{
uint8_t fun_code_ask = data[1]; // 功能码
uint8_t fun_ext_code_ask = data[2]; // 功能扩展码
uint8_t data_ask = data[4]; // 数据
uint8_t crc = crc8_check(data + 1, 4); // 计算响应信息的CRC,CRC8校验内容为从功能码到数据域所有数据的CRC8校验
if (crc == data[5]) // 计算的CRC与响应数据中的CRC结果一致
{
if ((data_ask == 0) && (fun_code_ask == fun_code) && (fun_ext_code_ask == fun_ext_code)) // 回复的数据是0,表示成功;校验响应的数据中的功能码和扩展码
{
return SENGDING_OK;
}
else
{
return SENDING_FAIL;
}
}
else
{
return SENDING_FAIL;
}
}
/**
* @brief 读取APP数据的CRC值
*
* @return uint16_t
*/
uint16_t C_Get_APPCodeCrc(void)
{
return *(uint16_t *)C_APP_CODE_CRC_ADDR;
}
///**
// * @brief 读取APP数据的CRC值
// *
// * @return uint16_t
// */
//uint16_t Get_FlashAPPCodeCrc(void)
//{
// uint16_t crc=0;
num=*(uint16_t *)C_APP_CODE_PACK_TOTAL_NUM_ADDR;
// crc=CRC16((unsigned char *)APP_CODE_ADDR_SART,4096);
// return crc;
//}
/**
* @brief 读取APP数据的总包数
*
* @return uint16_t
*/
uint16_t C_Get_APPCodeTotalNum(void)
{
uint16_t num=0;
num=*(uint16_t *)C_APP_CODE_PACK_TOTAL_NUM_ADDR;
return num;
}
/**
* @brief 从Flash地址读取128个字节的APP数据
*
* @param flash_address
* @param data_buffer
*/
void C_Read_App_Data(uint32_t flash_address, uint8_t *data_buffer)
{
for (uint8_t i = 0; i < 128; i++) // 只读取128字节的数据
{
data_buffer[i] = *((uint8_t *)(flash_address + i));
}
}
void C_Load_App(u32 appxaddr)
{
__disable_irq(); // 关闭所有中断
// uint8_t i;
if (((*(volatile uint32_t *)appxaddr) & 0x2FFE0000) == 0x20000000) // 检查栈顶地址是否合法.0x20000000是sram的起始地址,也是程序的栈顶地址
{
// 定义一个函数指针,指向应用程序的起始地址
void (*JumpToApp)(void) = (void (*)(void))(*((uint32_t *)(appxaddr + 4))); // 用户代码区第二个字为程序开始地址(复位地址)
__set_MSP(*(volatile uint32_t *)appxaddr);
JumpToApp(); // 跳转到APP.
}
}