fix:修改RS485通讯引脚

RS485通讯引脚改为串口2,引脚:RX:PB05 TX:PB04 RS485_DR:PB03
This commit is contained in:
caocong
2026-02-25 10:29:57 +08:00
commit 2815979c8a
77 changed files with 16491 additions and 0 deletions

1027
Source/SYSTEM/Bootload_fun.c Normal file

File diff suppressed because it is too large Load Diff

208
Source/SYSTEM/eeprom.c Normal file
View File

@@ -0,0 +1,208 @@
#include "includes.h"
#include <string.h>
E_MCU_DEV_INFO g_mcu_dev;
/*******************************************************************************
* Function Name : EEPROM_Init
* Description : EEPROM 初始化函数
*******************************************************************************/
void EEPROM_Init(void)
{
U8_T rev = 0;
EnIFCClk; //使能 IFC 时钟
IFC->MR |= 0x10002; //高速模式,延迟 2 个周期
delay_nms(10);
rev = EEPROM_ReadMCUDevInfo(&g_mcu_dev);
if(rev == 0x00){
//读取成功,开始校验以下参数
EEPROM_Validate_MCUDevInfo(&g_mcu_dev);
}else{
//读取失败,恢复默认参数
EEPROM_Default_MCUDevInfo(&g_mcu_dev);
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"EE Use Defalut Para");
Dbg_Println(DBG_BIT_SYS_STATUS,"EE DevBootVer:%d",g_mcu_dev.dev_boot_ver);
Dbg_Println(DBG_BIT_SYS_STATUS,"EE DevNameLen:%d",g_mcu_dev.dev_name_len);
Dbg_Println(DBG_BIT_SYS_STATUS,"EE DevName:%s",g_mcu_dev.dev_name);
#endif
}
}
/*******************************************************************************
* Function Name : EEPROM_CheckSum
* Description : EEPROM 校验函数
*******************************************************************************/
U8_T EEPROM_CheckSum(U8_T *data,U16_T len)
{
U8_T data_sum = 0;
for(U16_T i = 0;i<len;i++)
{
data_sum += data[i];
}
return data_sum;
}
/*******************************************************************************
* Function Name : EEPROM_ReadMCUDevInfo
* Description : 从EEPROM中读取设备信息
*******************************************************************************/
U8_T EEPROM_ReadMCUDevInfo(E_MCU_DEV_INFO *info)
{
U8_T read_info[6];
U8_T para_data[EEPROM_DATA_Size_Max];
U16_T read_len = 0;
memset(read_info,0,sizeof(read_info));
memset(para_data,0,sizeof(para_data));
ReadDataArry_U8(EEPROM_MCUDevInfo_Address,4,read_info);
if(read_info[0] == EEPROM_SVAE_FLAG){
read_len = read_info[2];
read_len <<= 8;
read_len |= read_info[1];
if(read_len <= EEPROM_DATA_Size_Max){
ReadDataArry_U8(EEPROM_MCUDevInfo_Address+EEPROM_Offset_Data,read_len,para_data);
if(EEPROM_CheckSum(para_data,sizeof(E_MCU_DEV_INFO)) == read_info[3]){
//校验成功
memcpy((uint8_t *)info,para_data,sizeof(E_MCU_DEV_INFO));
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"EE DevAddr:%d",g_mcu_dev.dev_addr);
Dbg_Println(DBG_BIT_SYS_STATUS,"EE DevType:%d",g_mcu_dev.dev_type);
Dbg_Println(DBG_BIT_SYS_STATUS,"EE DevBootVer:%d",g_mcu_dev.dev_boot_ver);
Dbg_Println(DBG_BIT_SYS_STATUS,"EE DevAppVer:%d",g_mcu_dev.dev_app_ver);
Dbg_Println(DBG_BIT_SYS_STATUS,"EE DevNameLen:%d",g_mcu_dev.dev_name_len);
Dbg_Println(DBG_BIT_SYS_STATUS,"EE DevName:%s",g_mcu_dev.dev_name);
#endif
return 0x00;
}
}
}
return 0x01;
}
/*******************************************************************************
* Function Name : EEPROM_WriteMCUDevInfo
* Description : 将设备信息写入到EEPROM中
*******************************************************************************/
U8_T EEPROM_WriteMCUDevInfo(E_MCU_DEV_INFO *info)
{
U8_T save_data[EEPROM_DATA_Size_Max + 6];
U16_T save_len = sizeof(E_MCU_DEV_INFO);
if(save_len >= EEPROM_DATA_Size_Max) save_len = EEPROM_DATA_Size_Max;
save_data[0] = EEPROM_SVAE_FLAG;
save_data[1] = save_len & 0xFF;
save_data[2] = (save_len >> 8) & 0xFF;
memcpy(&save_data[4],(uint8_t *)info,save_len);
save_data[3] = EEPROM_CheckSum(&save_data[4],save_len);
save_len+=4;
Page_ProgramData(EEPROM_MCUDevInfo_Address,save_len,save_data);
return 0;
}
/*******************************************************************************
* Function Name : EEPROM_Default_MCUDevInfo
* Description : EEPROM中参数恢复默认值且将默认参数保存至EEPROM中
*******************************************************************************/
void EEPROM_Default_MCUDevInfo(E_MCU_DEV_INFO *info)
{
#if (Project_Area == 0x01)
/*Boot 区域*/
info->dev_addr = 0x00;
info->dev_type = 0x00;
info->dev_app_ver = 0x00;
info->dev_boot_ver = Project_FW_Version;
info->dev_name_len = sizeof(Peoject_Name);
memset((char *)info->dev_name,0,EEPROM_DEV_NAME_Size);
memcpy((char *)info->dev_name,(char *)Peoject_Name,info->dev_name_len);
EEPROM_WriteMCUDevInfo(info);
#elif (Project_Area == 0x02)
/*APP 区域*/
info->dev_addr = 0x00;
info->dev_type = Project_Type;
info->dev_app_ver = Project_FW_Version;
info->dev_name_len = sizeof(Peoject_Name);
memset((char *)info->dev_name,0,EEPROM_DEV_NAME_Size);
memcpy((char *)info->dev_name,(char *)Peoject_Name,info->dev_name_len);
EEPROM_WriteMCUDevInfo(info);
#endif
}
/*******************************************************************************
* Function Name : EEPROM_Validate_MCUDevInfo
* Description : 校验从EEPROM 中读取的参数是否正确,如果不正确的话,便将当前正确的参数写入
APP区域中判断APP参数与EEPROM中记录的是否一致
Boot区域中判断Boot参数与EEPROM中记录的是否一致
*******************************************************************************/
void EEPROM_Validate_MCUDevInfo(E_MCU_DEV_INFO *info)
{
#if (Project_Area == 0x01)
/*Boot 区域*/
U8_T save_flag = 0;
if(info->dev_boot_ver != Project_FW_Version)
{
info->dev_boot_ver = Project_FW_Version;
save_flag = 0x01;
}
if(save_flag == 0x01)
{
EEPROM_WriteMCUDevInfo(info);
}
#elif (Project_Area == 0x02)
/*APP 区域*/
U8_T save_flag = 0;
if(info->dev_app_ver != Project_FW_Version)
{
info->dev_app_ver = Project_FW_Version;
save_flag = 0x01;
}
if(info->dev_type != Project_Type)
{
info->dev_type = Project_Type;
save_flag = 0x01;
}
if(info->dev_name_len != sizeof(Peoject_Name))
{
info->dev_name_len = sizeof(Peoject_Name);
save_flag = 0x01;
}
if(strncmp((char *)info->dev_name,(char *)Peoject_Name,sizeof(Peoject_Name)))
{
memcpy((char *)info->dev_name,(char *)Peoject_Name,info->dev_name_len);
save_flag = 0x01;
}
if(save_flag == 0x01)
{
EEPROM_WriteMCUDevInfo(info);
}
#endif
}

View File

@@ -0,0 +1,88 @@
#ifndef _BOOTLOAD_FUNCTION_H_
#define _BOOTLOAD_FUNCTION_H_
#include "apt32f102.h"
#include "apt32f102_ifc.h"
#include "apt32f102_syscon.h"
#include "uart.h"
#define App_Procedure_Ready 0x66 //APP准备就绪标志位
#define APP_Flash_PageSize 0x100
#if DBG_LOG_EN
#define APP_Flash_StartAddr PROM_PageAdd96 //调试APP起始地址
#else
#define APP_Flash_StartAddr PROM_PageAdd40
#endif
#define APP_Flash_EndAddr PROM_PageAdd255
#define APP_FEATURE_Flash_Addr PROM_PageAdd255
#define MCU_EEPROM_PageSize 0x40
#define MCU_EEPROM_StartAddr DROM_PageAdd0
#define MCU_EEPROM_EndAddr (DROM_PageAdd31 + MCU_EEPROM_PageSize)
#define BCOMM_CMD_Handshake 0xC0
#define BCOMM_CMD_Jump 0xC1
#define BCOMM_CMD_SetInfo 0xC2
#define BCOMM_CMD_WriteFlash 0xC3
#define BCOMM_CMD_ReadFlash 0xC4
#define BCOMM_CMD_EraseFlash 0xC5
#define BCOMM_CMD_WriteEEPROM 0xC6
#define BCOMM_CMD_ReadEEPROM 0xC7
#define BCOMM_CMD_EraseEEPROM 0xC8
#define BCOMM_CMD_CheckData 0xC9
#define BCOMM_CMD_ReplySUCC 0x00
#define BCOMM_CMD_ReplyFAIL 0x01
#define BCOMM_ACKSize 300
#define BCOMM_ParaSize 280
typedef enum
{
BCOMM_FMT_TXAddr,
BCOMM_FMT_SN,
BCOMM_FMT_TYPE,
BCOMM_FMT_RXAddr,
BCOMM_FMT_LEN_L,
BCOMM_FMT_LEN_H,
BCOMM_FMT_CKS,
BCOMM_FMT_CMD,
BCOMM_FMT_PARAM,
}BOOT_COMM_FMT_e;
typedef struct{
U8_T jump_start;
U8_T sn;
U8_T cmd;
U8_T pc_addr;
U8_T ackBuffer[BCOMM_ACKSize];
U16_T ackLen;
U16_T ackValidity; //数据回复有效期
U32_T bootTimeout;
U32_T bootTick;
}BOOT_INFO_T;
typedef struct{
U8_T crcL_check;
U8_T crcH_check;
U8_T app_flag;
U8_T app_crc[241];
U16_T app_crc_size;
U16_T app_crc_len;
U32_T app_start_addr;
U32_T app_end_addr;
}APP_FEATURE_INFO_T; /*字节空间是256Byte*/
extern BOOT_INFO_T g_boot;
void Boot_Function_Init(void);
U8_T Boot_Comm_UpgradeProcess(U8_T *data,U16_T len);
void Boot_Time_Refresh(void);
void Boot_TimeOut_Task(void);
void Jump_To_APP(void);
U8_T Check_APP_Feature(void);
#endif

View File

@@ -0,0 +1,51 @@
#ifndef _EEPROM_H_
#define _EEPROM_H_
#include "apt32f102.h"
/*地址范围0x10000000~0x100007FF*/
#define EEPROM_MCUDevInfo_Address 0x10000000 //MCU 设备信息地址固定为0x10000000大小为0x40 此区域不可改动
/* EEPROM 保存数据格式:
* FLAG - 1Byte 保存标志位
* LEN - 2Byte 保存数据长度
* CHECK - 1Byte 保存数据校验
* DATA - nByte 保存数据内容
*
* */
#define EEPROM_SVAE_FLAG 0xAE
#define EEPROM_DATA_Size_Max 0x40 //目前保存数据内容最长为100Byte
#define EEPROM_PARA_Size 50
#define EEPROM_DEV_NAME_Size 32
#define EEPROM_Offset_SaveFlag 0x00
#define EEPROM_Offset_Datalen 0x01
#define EEPROM_Offset_Check 0x03
#define EEPROM_Offset_Data 0x04
typedef struct{
U8_T dev_addr; //设备地址
U8_T dev_type; //设备类型
U8_T dev_boot_ver; //设备Boot的软件版本号
U8_T dev_app_ver; //设备APP的软件版本号
U8_T dev_name_len; //设备名称的长度
U8_T dev_name[EEPROM_DEV_NAME_Size]; //设备名称
}E_MCU_DEV_INFO;
extern E_MCU_DEV_INFO g_mcu_dev;
void EEPROM_Init(void);
U8_T EEPROM_ReadMCUDevInfo(E_MCU_DEV_INFO *info);
U8_T EEPROM_WriteMCUDevInfo(E_MCU_DEV_INFO *info);
void EEPROM_Default_MCUDevInfo(E_MCU_DEV_INFO *info);
void EEPROM_Validate_MCUDevInfo(E_MCU_DEV_INFO *info);
#endif

133
Source/SYSTEM/inc/uart.h Normal file
View File

@@ -0,0 +1,133 @@
#ifndef _UART_H_
#define _UART_H_
#include "apt32f102.h"
#include "apt32f102_uart.h"
#define Recv_2400_TimeOut 10 //ms
#define Recv_9600_TimeOut 5 //ms
#define Recv_115200_TimeOut 3 //ms
#define USART_BUFFER_SIZE 300
#define UART_SEND_BUFFER_NUM 10
#define UART_SEND_BUFFER_SIZE 20
#define READ_RXLEVEL_STATE GPIO_Read_Status(GPIOB0,5) //485总线RX引脚
#define WRITE_HIGH_DR GPIO_Write_High(GPIOB0,3) //485 DR
#define WRITE_LOW_DR GPIO_Write_Low(GPIOB0,3) //485 DR
#define REVERISE_DR GPIO_Reverse(GPIOB0,3) //485 DR
#define UART_BUSBUSY 0x01 //总线繁忙
#define UART_BUSIDLE 0x00 //总线空闲
/*调试信息相关定义*/
#ifndef DBG_LOG_EN
#define DBG_LOG_EN 0 //DEBUG LOG 输出总开关
#endif
/*调试信息初始状态*/
#define DBG_OPT_Debug_STATUS 0 //临时调试信息打印开关
#define DBG_OPT_DEVICE_STATUS 0 //设备驱动层打印调试信息打印开关
#define DBG_OPT_SYS_STATUS 0 //系统调试信息打印开关
/*调试信息输出控制位*/
#define DBG_BIT_Debug_STATUS 2
#define DBG_BIT_DEVICE_STATUS 1
#define DBG_BIT_SYS_STATUS 0
#if DBG_LOG_EN
#define DBG_SendByte(data) UARTTxByte(UART2,data)
#define DBG_Printf(data,len) UARTTransmit(UART2,data,len)
#else
#define DBG_SendByte(data)
#define DBG_Printf
#endif
typedef U8_T (*Uart_prt)(U8_T *,U16_T);
typedef enum
{
UART_0,
UART_1,
UART_2,
UART_3,
UART_MAX,
}UART_IDX;
typedef enum
{
BUSSEND_SUCC = 0x00, //发送成功
BUSSEND_WAIT, //等待发送机会
DATA_END, //数据有效期结束
RETRY_END, //重发结束
LEN_ERR, //长度错误
}BUSSEND_REV;
typedef struct{
U8_T RecvBuffer[USART_BUFFER_SIZE];
U8_T DealBuffer[USART_BUFFER_SIZE];
U8_T Receiving;
U16_T RecvLen;
U16_T DealLen;
U32_T RecvTimeout;
U32_T RecvIdleTiming;
Uart_prt processing_cf; //处理函数指针
} UART_t;
typedef struct{ //总线繁忙判断
U8_T SendBuffer[USART_BUFFER_SIZE]; //发送缓冲
U8_T BusState_Flag; //总线繁忙标记位, 0x01:总线繁忙0x00:总线空闲
U8_T HighBit_Flag; //串口RX高电平标记位,默认是高电平0x01.
U8_T BUSBUSY_LOCK; //锁定总线繁忙状态
U8_T ResendCnt; //当前发送次数
U8_T ASend_Flag; //主动上报发送标记
U8_T TotalCnt; //发送总次数
U8_T SetBaudFlag; //设置波特率
U16_T SendLen; //发送缓冲区数据长度
U32_T SetBaud;
U32_T Bus_DelayTime; //总线繁忙转换到空闲状态的随机延时时间
U32_T DataWait_Time; //上报数据间隔
U32_T DataValid_Time; //上报数据有效期
U32_T BusState_Tick; //总线繁忙状态判断时间戳
U32_T ASend_Tick; //主动上报发送间隔判断时间戳
U32_T BusbusyTimeout; //上报数据有效期判断时间戳
}MULIT_t;
extern U32_T Dbg_Switch;
extern volatile int RS485_Comm_Flag,RS485_Comm_Start,RS485_Comm_End,RS485_Comming;
void UARTx_Init(UART_IDX uart_id, Uart_prt prt_cf);
U16_T Get_Uart_BaudCnt(U32_T baud);
U8_T UARTx_ChangeBaud(uint8_t uart_id,uint32_t baud);
void UART2_RecvINT_Processing(char data);
void UART2_TASK(void);
void MCU485_SendData(U8_T *buff,U16_T len);
U8_T BUS485_Send(U8_T *buff,U16_T len);
U8_T MultSend_Task(U8_T *buff,U16_T len,U8_T DatSd);
void Set_GroupSend(U8_T *data,U16_T sled,U8_T SCnt,U32_T indate,U32_T tim_val);
//void Clear_SendFlag(void);
void BUS485_SetBaud(U32_T baud);
void BUS485Send_Task(void);
void BusIdle_Task(void);
void BusBusy_Task(void);
void Dbg_Print(int DbgOptBit, const char *cmd, ...);
void Dbg_Println(int DbgOptBit, const char *cmd, ...);
void Dbg_Print_Buff(int DbgOptBit, const char *cmd, U8_T *buff,U16_T len);
#endif

627
Source/SYSTEM/uart.c Normal file
View File

@@ -0,0 +1,627 @@
#include "includes.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
/**
* Bootload 串口使用情况
* UART0 没有使用
* UART2 用与调试信息输出 - 512000
* UART1 用于Bootload 升级使用
* */
UART_t g_uart; //目前该项目只使用串口2 进行双向通讯
MULIT_t m_send;
void UARTx_Init(UART_IDX uart_id, Uart_prt prt_cf) {
switch(uart_id){
case UART_1:
memset(&g_uart,0,sizeof(UART_t));
memset(&m_send,0,sizeof(MULIT_t));
//串口1-RX接收中断用于串口1的通讯总线繁忙状态判断2025-04-16
// GPIO_PullHigh_Init(GPIOA0,15);
// GPIO_IntGroup_Set(PA0,15,Selete_EXI_PIN15); //EXI0 set PB0.2
// GPIOA0_EXI_Init(EXI15); //PB0.2 as input
// EXTI_trigger_CMD(ENABLE,EXI_PIN15,_EXIFT); //ENABLE falling edge
// EXTI_trigger_CMD(ENABLE,EXI_PIN15,_EXIRT);
// EXTI_interrupt_CMD(ENABLE,EXI_PIN15); //enable EXI
// GPIO_EXTI_interrupt(GPIOA0,0b1000000000000000); //enable GPIOB02 as EXI
// EXI4_Int_Enable();
//
// UART1_DeInit(); //clear all UART Register
// UART_IO_Init(IO_UART1,2); //use PA0.13->RXD1, PB0.0->TXD1
// UARTInitRxTxIntEn(UART1,20000,UART_PAR_NONE); //baudrate=sysclock 48M/20000=2400 tx rx int enabled
// UART1_Int_Enable();
//
// m_send.BusState_Tick = SysTick_1ms;
// m_send.HighBit_Flag = 0x01;
//
// g_uart.RecvTimeout = Recv_2400_TimeOut;
// g_uart.processing_cf = prt_cf;
//
// //485使能引脚初始化
// GPIO_Init(GPIOA0,UART485_DR_PIN,Output);
// GPIO_DriveStrength_EN(GPIOA0,UART485_DR_PIN);
// WRITE_LOW_DR;
break;
case UART_2:
//2026-02-06 使用串口2作为Bootload 升级使用
memset(&g_uart,0,sizeof(UART_t));
memset(&m_send,0,sizeof(MULIT_t));
//串口RX接收中断
GPIO_PullHigh_Init(GPIOB0,5);
GPIO_IntGroup_Set(PB0,5,Selete_EXI_PIN5); //EXI0 set PB0.5
GPIOB0_EXI_Init(EXI5); //PB0.5 as input
EXTI_trigger_CMD(ENABLE,EXI_PIN5,_EXIFT); //ENABLE falling edge
EXTI_trigger_CMD(ENABLE,EXI_PIN5,_EXIRT);
EXTI_interrupt_CMD(ENABLE,EXI_PIN5); //enable EXI
GPIO_EXTI_interrupt(GPIOB0,0b0000000000100000); //enable GPIOB05 as EXI
EXI3_Int_Enable(); //EXI4~EXI9 INT Vector
UART2_DeInit(); //clear all UART Register
UART_IO_Init(IO_UART2,2); //use PA0.13->RXD1, PB0.0->TXD1
UARTInitRxTxIntEn(UART2,20000,UART_PAR_NONE); //baudrate=sysclock 48M/416=115200 tx rx int enabled
UART2_Int_Enable();
m_send.BusState_Tick = SysTick_1ms;
m_send.HighBit_Flag = 0x01;
g_uart.RecvTimeout = Recv_2400_TimeOut;
g_uart.processing_cf = prt_cf;
//485使能引脚初始化
GPIO_Init(GPIOB0,3,Output);
GPIO_DriveStrength_EN(GPIOB0,3);
WRITE_LOW_DR;
break;
}
}
/*******************************************************************************
* Function Name : Get_Uart_BaudCnt
* Description : Uart 获取串口波特率对于设置值
*******************************************************************************/
U16_T Get_Uart_BaudCnt(U32_T baud)
{
switch(baud){
case 2400:
return 20000;
case 4800:
return 10000;
case 9600:
return 5000;
case 19200:
return 2621;
case 56000:
return 898;
case 115200:
return 416;
case 512000:
return 98;
}
return 0x00;
}
/*******************************************************************************
* Function Name : Get_Uart_Recv_Timeout
* Description : Uart 获取串口接收超时时间
*******************************************************************************/
U32_T Get_Uart_Recv_Timeout(U32_T baud)
{
switch(baud){
case 2400:
return Recv_2400_TimeOut;
case 4800:
return Recv_2400_TimeOut;
case 9600:
return Recv_9600_TimeOut;
case 19200:
return Recv_9600_TimeOut;
case 56000:
return Recv_9600_TimeOut;
case 115200:
return Recv_115200_TimeOut;
case 512000:
return Recv_115200_TimeOut;
}
return Recv_115200_TimeOut;
}
/*******************************************************************************
* Function Name : UARTx_ChangeBaud
* Description : Uart 切换串口波特率
*******************************************************************************/
U8_T UARTx_ChangeBaud(uint8_t uart_id,uint32_t baud)
{
U16_T set_para = Get_Uart_BaudCnt(baud);
if(set_para == 0x00) return 0x01; //设置的波特率不支持
switch(uart_id){
case UART_1:
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS, "UART ID %d", uart_id);
Dbg_Println(DBG_BIT_SYS_STATUS,"UART baud %d",baud);
#endif
UARTClose(UART1);
UART1_Int_Disable();
UART1_DeInit(); //clear all UART Register
UART_IO_Init(IO_UART1,2); //use PA0.13->RXD1, PB0.0->TXD1
UARTInitRxTxIntEn(UART1,set_para,UART_PAR_NONE); //baudrate=sysclock 48M/416=115200 tx rx int enabled
UART1_Int_Enable();
g_uart.RecvTimeout = Get_Uart_Recv_Timeout(baud);
break;
case UART_2:
UARTClose(UART2);
UART2_Int_Disable();
UART2_DeInit(); //clear all UART Register
UART_IO_Init(IO_UART2,2); //use PA0.13->RXD1, PB0.0->TXD1
UARTInitRxTxIntEn(UART2,set_para,UART_PAR_NONE); //baudrate=sysclock 48M/416=115200 tx rx int enabled
UART2_Int_Enable();
g_uart.RecvTimeout = Get_Uart_Recv_Timeout(baud);
break;
}
}
/*******************************************************************************
* Function Name : UART1_RecvINT_Processing
* Description : 串口1 接收中断处理函数 - 接收中断调用
*******************************************************************************/
//void UART1_RecvINT_Processing(char data){
// if((g_uart.RecvLen + 1) >= USART_BUFFER_SIZE) g_uart.RecvLen = 0;
// g_uart.RecvBuffer[g_uart.RecvLen++] = (U8_T)data;
//
// g_uart.RecvIdleTiming = SysTick_1ms;
// g_uart.Receiving = 0x01;
//}
//
//
//void UART1_TASK(void){
// U8_T ret = 0x00;
// if(g_uart.Receiving == 0x01){
// if(SysTick_1ms - g_uart.RecvIdleTiming > g_uart.RecvTimeout){
//
// SYSCON_Int_Disable();
// g_uart.RecvIdleTiming = SysTick_1ms;
// memcpy(g_uart.DealBuffer,g_uart.RecvBuffer,g_uart.RecvLen);
// g_uart.DealLen = g_uart.RecvLen;
// g_uart.RecvLen = 0;
// g_uart.Receiving = 0;
// SYSCON_Int_Enable();
//
//#if DBG_LOG_EN
// Dbg_Println(DBG_BIT_SYS_STATUS, "UART recv Len %d", g_uart.DealLen);
// Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"UART buff",g_uart.DealBuffer,g_uart.DealLen);
//#endif
//
// if(g_uart.processing_cf != NULL){
// ret = g_uart.processing_cf(g_uart.DealBuffer,g_uart.DealLen);
// }
//
// }
// }
//}
/*******************************************************************************
* Function Name : UART2_RecvINT_Processing
* Description : 串口2 接收中断处理函数 - 接收中断调用
*******************************************************************************/
void UART2_RecvINT_Processing(char data){
if((g_uart.RecvLen + 1) >= USART_BUFFER_SIZE) g_uart.RecvLen = 0;
g_uart.RecvBuffer[g_uart.RecvLen++] = (U8_T)data;
g_uart.RecvIdleTiming = SysTick_1ms;
g_uart.Receiving = 0x01;
}
void UART2_TASK(void){
U8_T ret = 0x00;
if(g_uart.Receiving == 0x01){
if(SysTick_1ms - g_uart.RecvIdleTiming > g_uart.RecvTimeout){
SYSCON_Int_Disable();
g_uart.RecvIdleTiming = SysTick_1ms;
memcpy(g_uart.DealBuffer,g_uart.RecvBuffer,g_uart.RecvLen);
g_uart.DealLen = g_uart.RecvLen;
g_uart.RecvLen = 0;
g_uart.Receiving = 0;
SYSCON_Int_Enable();
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS, "UART recv Len %d", g_uart.DealLen);
Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"UART buff",g_uart.DealBuffer,g_uart.DealLen);
#endif
if(g_uart.processing_cf != NULL){
ret = g_uart.processing_cf(g_uart.DealBuffer,g_uart.DealLen);
}
}
}
}
/*因为开启了UART_TX_DONE_S 中断,发送完成需要清楚该中断标志位,因此每次调用串口输出后,需调用该函数,否则会在中断出不来
* 已取消
* */
void UART_Waiting_For_Send(CSP_UART_T *uart){
unsigned int Dataval = 0,delay_cnt = 0;
do{
Dataval = CSP_UART_GET_ISR(uart);
Dataval = Dataval & UART_TX_DONE_S;
delay_cnt ++;
if(delay_cnt >= 50000){
break;
}
}while(Dataval == 0x00); //发送完成
uart->ISR=UART_TX_DONE_S;
}
volatile int RS485_Comm_Flag = 0,RS485_Comm_Start = 0,RS485_Comm_End = 0,RS485_Comming = 0;
void MCU485_SendData(U8_T *buff,U16_T len){
unsigned int Dataval = 0,delay_cnt = 0;
//等待通讯发送完成
while(RS485_Comming == 0x01){
delay_nus(100);
delay_cnt ++;
if(delay_cnt >= 100){
break;
}
REVERISE_DR;//GPIO_Reverse(GPIOB0,3);
}
WRITE_HIGH_DR;//GPIO_Write_High(GPIOB0,3);
RS485_Comm_Flag = 0x01;
RS485_Comm_Start = 0x00;
RS485_Comm_End = 0x00;
UARTTransmit(UART2,buff,len);
do{
delay_nus(100);
delay_cnt ++;
if(delay_cnt >= 100){
break;
}
}while((RS485_Comm_Start < len) || (RS485_Comm_End < len)); //发送完成
WRITE_LOW_DR;//GPIO_Write_Low(GPIOB0,3);
RS485_Comm_Flag = 0x00;
}
/**********************************************************
* @brief BUS485 数据发生函数 - 检测总线是否繁忙,空闲状态下,才发生数据;繁忙状态下,直接退出
* @retval None
* */
U8_T BUS485_Send(U8_T *buff,U16_T len)
{
unsigned int Dataval = 0,delay_cnt = 0;
//等待通讯发送完成
while(RS485_Comming == 0x01){
delay_nus(100);
delay_cnt ++;
if(delay_cnt >= 100){
break;
}
REVERISE_DR;//GPIO_Reverse(GPIOB0,3);
}
if(m_send.BusState_Flag == UART_BUSIDLE){ //总线空闲
CK_CPU_DisAllNormalIrq();
WRITE_HIGH_DR;//GPIO_Write_High(GPIOB0,3);
RS485_Comm_Flag = 0x01;
RS485_Comm_Start = 0x00;
RS485_Comm_End = 0x00;
m_send.BusState_Flag = UART_BUSBUSY;//发送前总线置位繁忙
m_send.BUSBUSY_LOCK = 0x01; //锁定总线状态
CK_CPU_EnAllNormalIrq();
UARTTransmit(UART2,buff,len);
do{
delay_nus(100);
delay_cnt ++;
if(delay_cnt >= 100){
break;
}
}while((RS485_Comm_Start < len) || (RS485_Comm_End < len)); //发送完成
CK_CPU_DisAllNormalIrq();
WRITE_LOW_DR;//GPIO_Write_Low(GPIOB0,3);
RS485_Comm_Flag = 0x00;
m_send.BusState_Tick = SysTick_1ms;
m_send.BUSBUSY_LOCK = 0x00; //解锁总线状态
CK_CPU_EnAllNormalIrq();
return UART_BUSIDLE; //发送成功
}
else{ //总线繁忙
return UART_BUSBUSY; //发送失败
}
return 0x02; //传入状态无效
}
/**********************************************************
* @brief 重发、数据有效期、超时发送判断2025-03-25
* buff:发送数据
* len数据长度
* DatSd发送标记,0x00:无发送0x01有数据发送
*
* @retval 0x00:发送成功 0x01:等待发送 0x02:数据无效
* */
U8_T MultSend_Task(U8_T *buff,U16_T len,U8_T DatSd)
{
if( (len == 0)||(len > USART_BUFFER_SIZE) ) return LEN_ERR;
if(DatSd == 0x01)
{
if( m_send.ResendCnt < m_send.TotalCnt) //判断数据是否还在有效期,是否还有发送次数
{
if(SysTick_1ms - m_send.BusbusyTimeout < m_send.DataValid_Time)
{
if( (m_send.ResendCnt == 0x00) || (SysTick_1ms - m_send.ASend_Tick >= m_send.DataWait_Time) ){//数据发送间隔
if(BUS485_Send(buff,len) == UART_BUSIDLE){ //发送数据
m_send.ASend_Tick = SysTick_1ms;
m_send.ResendCnt++;
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_Debug_STATUS,"SendCnt:%d success",m_send.ResendCnt);
#endif
return BUSSEND_SUCC;//数据发送成功
}
}
}else{
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_Debug_STATUS,"data end");
#endif
return DATA_END;//数据有效期结束
}
}else{
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_Debug_STATUS,"retry end,%d",m_send.ResendCnt );
#endif
return RETRY_END;//没有重发次数
}
}
return BUSSEND_WAIT;//等待
}
/**********************************************************
* @brief 设置发送标志、组包、选择数据有效期档位2025-03-25
* data: 发送数据
* sled 数据长度
* SCnt: 设置数据发送次数
* indate 设置数据有效期
* tim_val: 发送时间间隔
* @retval None
* */
void Set_GroupSend(U8_T *data,U16_T sled,U8_T SCnt,U32_T indate,U32_T tim_val)
{
if((sled == 0x00)|| (sled > USART_BUFFER_SIZE)) return;
memset(m_send.SendBuffer,0, USART_BUFFER_SIZE);
memcpy(m_send.SendBuffer,data,sled);
m_send.SendLen = sled;
m_send.DataValid_Time = indate;//数据有效期
m_send.TotalCnt = SCnt; //数据发送次数
m_send.DataWait_Time = tim_val;//发送数据间隔
m_send.ASend_Flag = 0x01;
m_send.ResendCnt = 0x00;
m_send.BusbusyTimeout = SysTick_1ms;
}
//清除发送标志
//void Clear_SendFlag(void)
//{
// m_send.ASend_Flag = 0x00;
//}
void BUS485_SetBaud(U32_T baud)
{
m_send.SetBaudFlag = 0x01;
m_send.SetBaud = baud;
}
/**********************************************************
* @brief 检测总线空闲在While(1)里调用 2025-03-25
* @retval None
* */
void BUS485Send_Task(void) //2025-03-29
{
U8_T ret = 0xFF;
//空闲等待
if(m_send.ASend_Flag == 0x01)//初始化发送
{
ret = MultSend_Task(m_send.SendBuffer,m_send.SendLen,m_send.ASend_Flag);
if( (ret == DATA_END)||(ret == RETRY_END) )//判断发送数据是否有效
{
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_Debug_STATUS,"send end");
#endif
m_send.ASend_Flag = 0x00;
/*设置波特率*/
if( m_send.SetBaudFlag == 0x01 ){
UARTx_ChangeBaud(UART_2,m_send.SetBaud);
m_send.SetBaudFlag = 0x00;
m_send.SetBaud = 0x00;
}
}
}
}
/**********************************************************
* @brief 检测总线空闲,在定时器中断里调用
* @retval None
* */
void BusIdle_Task(void)
{
if(m_send.BusState_Flag != UART_BUSIDLE && m_send.BUSBUSY_LOCK != 0x01)
{
CK_CPU_DisAllNormalIrq();
if( ( m_send.HighBit_Flag == 0x01 )&&( ( SysTick_1ms - m_send.BusState_Tick ) >= ( g_uart.RecvTimeout + m_send.Bus_DelayTime )) )
{
m_send.BusState_Flag = UART_BUSIDLE;
}
CK_CPU_EnAllNormalIrq();
}
}
/*******************************************************************
* @brief 检测总线繁忙在串口接收RX引脚的外部中断服务函数里调用
* @retval None
* */
void BusBusy_Task(void)
{
CK_CPU_DisAllNormalIrq();
m_send.BusState_Flag = UART_BUSBUSY;
m_send.BusState_Tick = SysTick_1ms;
m_send.Bus_DelayTime = (SysTick_1ms - m_send.ASend_Tick)%10;//随机延时
if(READ_RXLEVEL_STATE == 0x01){
m_send.HighBit_Flag = 0x01; //高电平标志置位
}else if(READ_RXLEVEL_STATE == 0x00){
m_send.HighBit_Flag = 0x00; //低电平
}
CK_CPU_EnAllNormalIrq();
}
/*调试信息输出接口*/
U32_T Dbg_Switch = (DBG_OPT_Debug_STATUS << DBG_BIT_Debug_STATUS)
+ (DBG_OPT_DEVICE_STATUS << DBG_BIT_DEVICE_STATUS)
+ (DBG_OPT_SYS_STATUS << DBG_BIT_SYS_STATUS);
#if DBG_LOG_EN
char Dbg_Buffer[512] = {0};
U32_T SysTick_Now = 0, SysTick_Last = 0, SysTick_Diff = 0;
#endif
void Dbg_Print(int DbgOptBit, const char *cmd, ...){
#if DBG_LOG_EN
U16_T str_offset = 0;
if (Dbg_Switch & (1 << DbgOptBit)) {
SysTick_Now = SysTick_1ms;
SysTick_Diff = SysTick_Now - SysTick_Last; //上一次打印时间差
SysTick_Last = SysTick_Now;
str_offset = snprintf(Dbg_Buffer, sizeof(Dbg_Buffer),"%8d [%6d]: ", SysTick_Now, SysTick_Diff);
DBG_Printf((U8_T *)Dbg_Buffer,str_offset);
va_list args; //定义一个va_list类型的变量用来储存单个参数
va_start(args, cmd); //使args指向可变参数的第一个参数
str_offset = vsnprintf(Dbg_Buffer, sizeof(Dbg_Buffer) ,cmd, args); //必须用vprintf等带V的
va_end(args); //结束可变参数的获取
DBG_Printf((U8_T *)Dbg_Buffer,str_offset);
}
#endif
}
void Dbg_Println(int DbgOptBit, const char *cmd, ...){
#if DBG_LOG_EN
U16_T str_offset = 0;
if (Dbg_Switch & (1 << DbgOptBit)) {
SysTick_Now = SysTick_1ms;
SysTick_Diff = SysTick_Now - SysTick_Last; //上一次打印时间差
SysTick_Last = SysTick_Now;
str_offset = snprintf(Dbg_Buffer, sizeof(Dbg_Buffer) , "%8ld [%6ld]: ", SysTick_Now, SysTick_Diff);
DBG_Printf((U8_T *)Dbg_Buffer,str_offset);
va_list args; //定义一个va_list类型的变量用来储存单个参数
va_start(args, cmd); //使args指向可变参数的第一个参数
str_offset = vsnprintf(Dbg_Buffer, sizeof(Dbg_Buffer) ,cmd, args); //必须用vprintf等带V的
va_end(args); //结束可变参数的获取
DBG_Printf((U8_T *)Dbg_Buffer,str_offset);
DBG_Printf((U8_T *)"\r\n",2);
}
#endif
}
void Dbg_Print_Buff(int DbgOptBit, const char *cmd, U8_T *buff,U16_T len){
#if DBG_LOG_EN
U16_T str_offset = 0;
if (Dbg_Switch & (1 << DbgOptBit)) {
SysTick_Now = SysTick_1ms;
SysTick_Diff = SysTick_Now - SysTick_Last; //上一次打印时间差
SysTick_Last = SysTick_Now;
str_offset = snprintf(Dbg_Buffer, sizeof(Dbg_Buffer) , "%8ld [%6ld]:%s ", SysTick_Now, SysTick_Diff,cmd);
DBG_Printf((U8_T *)Dbg_Buffer,str_offset);
for (uint32_t i = 0; i < len; i++) {
SYSCON_IWDCNT_Reload();
str_offset = snprintf(Dbg_Buffer, sizeof(Dbg_Buffer) , "%02X ", buff[i]);
DBG_Printf((U8_T *)Dbg_Buffer,str_offset);
}
DBG_Printf((U8_T *)"\r\n",2);
}
#endif
}