H743的CAN介绍
对比F1、F4系列的单片机,H7的CAN做出了全面的优化升级;相较于之前的CAN设有固定的滤波器组,和FIFO;H7则直接使用了10KB的共享消息RAM进行数据的存储与配置。使得数据的处理量大大增加。
初始化CAN1
FDCAN_HandleTypeDef FDCAN1_Handler;
FDCAN_RxHeaderTypeDef FDCAN1_RxHeader;
FDCAN_TxHeaderTypeDef FDCAN1_TxHeader;
//初始化FDCAN1,波特率为500Kbit/S
//配置FDCAN1的时钟源为PLL1Q=200Mhz
//presc:分频值,取值范围1~512
//ntsjw:重新同步跳跃时间单元.范围:1~128
//ntsg1: 取值范围2~256
//ntsg2: 取值范围2~128
//mode:FDCAN_MODE_NORMAL,普通模式;FDCAN_MODE_EXTERNAL_LOOPBACK,回环模式;
//返回值:0,初始化OK;
// 其他,初始化失败;
u8 FDCAN1_Mode_Init(u16 presc,u8 ntsjw,u16 ntsg1,u8 ntsg2,u32 mode)
{
FDCAN_FilterTypeDef FDCAN1_RXFilter;
//初始化FDCAN1
HAL_FDCAN_DeInit(&FDCAN1_Handler); //先清除以前的设置
FDCAN1_Handler.Instance=FDCAN1;
FDCAN1_Handler.Init.FrameFormat=FDCAN_FRAME_CLASSIC; //传统模式 不变波特率
FDCAN1_Handler.Init.Mode=mode; //普通模式
FDCAN1_Handler.Init.AutoRetransmission=DISABLE; //关闭自动重传!传统模式下一定要关闭!!!
FDCAN1_Handler.Init.TransmitPause=DISABLE; //关闭传输暂停
FDCAN1_Handler.Init.ProtocolException=DISABLE; //协议异常处理
FDCAN1_Handler.Init.NominalPrescaler=presc; //分频系数
FDCAN1_Handler.Init.NominalSyncJumpWidth=ntsjw; //重新同步跳跃宽度
FDCAN1_Handler.Init.NominalTimeSeg1=ntsg1; //tsg1范围:2~256
FDCAN1_Handler.Init.NominalTimeSeg2=ntsg2; //tsg2范围:2~128
FDCAN1_Handler.Init.DataPrescaler = 0x0A; /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck),范围1-32 */
FDCAN1_Handler.Init.DataSyncJumpWidth = 0x04; /* 用于动态调节 Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16 */
FDCAN1_Handler.Init.DataTimeSeg1 = 0x05; /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1,范围 */
FDCAN1_Handler.Init.DataTimeSeg2 = 0x04; /* 对应位时间特性图的 Phase_Seg2 */
FDCAN1_Handler.Init.MessageRAMOffset=0; //信息RAM偏移 /* CAN1和CAN2共享2560个字, 这里CAN1分配前1280字 */
FDCAN1_Handler.Init.StdFiltersNbr = 0; /* 设置标准ID过滤器个数,范围0-128 */
FDCAN1_Handler.Init.ExtFiltersNbr = 2; /* 设置扩展ID过滤器个数,范围0-64 */
FDCAN1_Handler.Init.RxFifo0ElmtsNbr = 4; /* 设置Rx FIFO0的元素个数,范围0-64 */ //通常 1个滤波器在列表模式下是两个 数据元素
FDCAN1_Handler.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; /* 设置Rx FIFO0中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */
FDCAN1_Handler.Init.RxFifo1ElmtsNbr = 0; /* 设置Rx FIFO1的元素个数,范围0-64 */
FDCAN1_Handler.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8; /* 设置Rx FIFO1中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */
FDCAN1_Handler.Init.RxBuffersNbr = 0; /* 设置Rx Buffer个数,范围0-64 */
FDCAN1_Handler.Init.RxBufferSize = 0; /* 设置Rx Buffer中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */
FDCAN1_Handler.Init.TxEventsNbr=0; //发送事件编号
FDCAN1_Handler.Init.TxBuffersNbr=0; //发送缓冲编号
FDCAN1_Handler.Init.TxFifoQueueElmtsNbr=1; //发送FIFO序列元素编号
FDCAN1_Handler.Init.TxFifoQueueMode=FDCAN_TX_FIFO_OPERATION; //发送FIFO序列模式
FDCAN1_Handler.Init.TxElmtSize=FDCAN_DATA_BYTES_8; //发送大小:8字节
if(HAL_FDCAN_Init(&FDCAN1_Handler)!=HAL_OK) return 1; //初始化FDCAN
//配置RX滤波器
FDCAN1_RXFilter.IdType=FDCAN_EXTENDED_ID; //扩展帧ID
FDCAN1_RXFilter.FilterIndex=0; //滤波器索引
FDCAN1_RXFilter.FilterType=FDCAN_FILTER_DUAL; //滤波器类型 专用ID
FDCAN1_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0; //过滤器0关联到FIFO0
FDCAN1_RXFilter.FilterID1=0x0CF00400; //发动机转速 扭矩 //32位ID
FDCAN1_RXFilter.FilterID2=0x18FEF700; /发动机输入电压 //如果FDCAN配置为传统模式的话,这里是32位掩码
if(HAL_FDCAN_ConfigFilter(&FDCAN1_Handler,&FDCAN1_RXFilter)!=HAL_OK) return 2;//滤波器初始化
FDCAN1_RXFilter.IdType=FDCAN_EXTENDED_ID; //扩展帧ID
FDCAN1_RXFilter.FilterIndex=1; //滤波器索引
FDCAN1_RXFilter.FilterType=FDCAN_FILTER_DUAL; //滤波器类型 专用ID
FDCAN1_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0; //过滤器0关联到FIFO0
FDCAN1_RXFilter.FilterID1=0x18FEEE00; ///发动机冷却液温度 //32位ID
FDCAN1_RXFilter.FilterID2=0xFFFFFFFF; //如果FDCAN配置为传统模式的话,这里是32位掩码
if(HAL_FDCAN_ConfigFilter(&FDCAN1_Handler,&FDCAN1_RXFilter)!=HAL_OK) return 2;//滤波器初始化
HAL_FDCAN_ConfigGlobalFilter(&FDCAN1_Handler,FDCAN_REJECT,FDCAN_REJECT,ENABLE,ENABLE);
HAL_FDCAN_Start(&FDCAN1_Handler); //开启FDCAN
HAL_FDCAN_ActivateNotification(&FDCAN1_Handler,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
return 0;
}
注意滤波器的个数和元素的对应 这里使用的是列表法过滤数据
只使用了FIFIO0的接收!
初始化CAN2
//初始化FDCAN2,波特率为500Kbit/S
//配置FDCAN1的时钟源为PLL1Q=200Mhz
//presc:分频值,取值范围1~512
//ntsjw:重新同步跳跃时间单元.范围:1~128
//ntsg1: 取值范围2~256
//ntsg2: 取值范围2~128
//mode:FDCAN_MODE_NORMAL,普通模式;FDCAN_MODE_EXTERNAL_LOOPBACK,回环模式;
//返回值:0,初始化OK;
// 其他,初始化失败;
u8 FDCAN2_Mode_Init(u16 presc,u8 ntsjw,u16 ntsg1,u8 ntsg2,u32 mode)
{
FDCAN_FilterTypeDef FDCAN2_RXFilter;
//初始化FDCAN1
HAL_FDCAN_DeInit(&FDCAN2_Handler); //先清除以前的设置
FDCAN2_Handler.Instance=FDCAN2;
FDCAN2_Handler.Init.FrameFormat=FDCAN_FRAME_CLASSIC; //传统模式 不变波特率
FDCAN2_Handler.Init.Mode=mode; //普通模式
FDCAN2_Handler.Init.AutoRetransmission=DISABLE; //关闭自动重传!传统模式下一定要关闭!!!
FDCAN2_Handler.Init.TransmitPause=DISABLE; //关闭传输暂停
FDCAN2_Handler.Init.ProtocolException=ENABLE; //协议异常处理
FDCAN2_Handler.Init.NominalPrescaler=presc; //分频系数
FDCAN2_Handler.Init.NominalSyncJumpWidth=ntsjw; //重新同步跳跃宽度
FDCAN2_Handler.Init.NominalTimeSeg1=ntsg1; //tsg1范围:2~256
FDCAN2_Handler.Init.NominalTimeSeg2=ntsg2; //tsg2范围:2~128
FDCAN2_Handler.Init.DataPrescaler = 0x0A; /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck),范围1-32 */
FDCAN2_Handler.Init.DataSyncJumpWidth = 0x04; /* 用于动态调节 Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16 */
FDCAN2_Handler.Init.DataTimeSeg1 = 0x05; /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1,范围 */
FDCAN2_Handler.Init.DataTimeSeg2 = 0x04; /* 对应位时间特性图的 Phase_Seg2 */
FDCAN2_Handler.Init.MessageRAMOffset=1280; //信息RAM偏移 /* CAN1和CAN2共享2560个字, 这里CAN1分配前1280字 */
FDCAN2_Handler.Init.StdFiltersNbr = 0; /* 设置标准ID过滤器个数,范围0-128 */
FDCAN2_Handler.Init.ExtFiltersNbr = 1; /* 设置扩展ID过滤器个数,范围0-64 */
FDCAN2_Handler.Init.RxFifo0ElmtsNbr = 2; /* 设置Rx FIFO0的元素个数,范围0-64 */ //通常 1个滤波器在列表模式下是两个 数据元素
FDCAN2_Handler.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; /* 设置Rx FIFO0中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */
FDCAN2_Handler.Init.RxFifo1ElmtsNbr = 0; /* 设置Rx FIFO1的元素个数,范围0-64 */
FDCAN2_Handler.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8; /* 设置Rx FIFO1中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */
FDCAN2_Handler.Init.RxBuffersNbr = 0; /* 设置Rx Buffer个数,范围0-64 */
FDCAN2_Handler.Init.RxBufferSize = 0; /* 设置Rx Buffer中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */
FDCAN2_Handler.Init.TxEventsNbr=0; //发送事件编号
FDCAN2_Handler.Init.TxBuffersNbr=0; //发送缓冲编号
FDCAN2_Handler.Init.TxFifoQueueElmtsNbr=1; //发送FIFO序列元素编号
FDCAN2_Handler.Init.TxFifoQueueMode=FDCAN_TX_FIFO_OPERATION; //发送FIFO序列模式
FDCAN2_Handler.Init.TxElmtSize=FDCAN_DATA_BYTES_8; //发送大小:8字节
if(HAL_FDCAN_Init(&FDCAN2_Handler)!=HAL_OK) return 1; //初始化FDCAN
//配置RX滤波器
FDCAN2_RXFilter.IdType=FDCAN_STANDARD_ID; //标准帧ID //扩展帧ID
FDCAN2_RXFilter.FilterIndex=0; //滤波器索引
FDCAN2_RXFilter.FilterType=FDCAN_FILTER_DUAL; //滤波器类型 列表 FDCAN_FILTER_DUAL 掩码 FDCAN_FILTER_MASK 范围FDCAN_FILTER_RANGE
FDCAN2_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0; //过滤器0关联到FIFO0
FDCAN2_RXFilter.FilterID1=0x179; //32位ID
FDCAN2_RXFilter.FilterID2=0x180; //如果FDCAN配置为传统模式的话,这里是32位掩码
if(HAL_FDCAN_ConfigFilter(&FDCAN2_Handler,&FDCAN2_RXFilter)!=HAL_OK) return 2;//滤波器初始化
FDCAN2_RXFilter.IdType=FDCAN_STANDARD_ID; //标准帧ID //扩展帧ID
FDCAN2_RXFilter.FilterIndex=1; //滤波器索引
FDCAN2_RXFilter.FilterType=FDCAN_FILTER_DUAL; //滤波器类型 列表 FDCAN_FILTER_DUAL 掩码 FDCAN_FILTER_MASK 范围FDCAN_FILTER_RANGE
FDCAN2_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0; //过滤器0关联到FIFO0
FDCAN2_RXFilter.FilterID1=0x285; //32位ID
FDCAN2_RXFilter.FilterID2=0x188; //如果FDCAN配置为传统模式的话,这里是32位掩码
if(HAL_FDCAN_ConfigFilter(&FDCAN2_Handler,&FDCAN2_RXFilter)!=HAL_OK) return 2;//滤波器初始化
FDCAN2_RXFilter.IdType=FDCAN_STANDARD_ID; //标准帧ID //扩展帧ID
FDCAN2_RXFilter.FilterIndex=2; //滤波器索引
FDCAN2_RXFilter.FilterType=FDCAN_FILTER_DUAL; //滤波器类型 列表 FDCAN_FILTER_DUAL 掩码 FDCAN_FILTER_MASK 范围FDCAN_FILTER_RANGE
FDCAN2_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0; //过滤器0关联到FIFO0
FDCAN2_RXFilter.FilterID1=0x288; //32位ID
FDCAN2_RXFilter.FilterID2=0x488; //如果FDCAN配置为传统模式的话,这里是32位掩码
if(HAL_FDCAN_ConfigFilter(&FDCAN2_Handler,&FDCAN2_RXFilter)!=HAL_OK) return 2;//滤波器初始化
HAL_FDCAN_ConfigGlobalFilter(&FDCAN2_Handler,FDCAN_REJECT,FDCAN_REJECT,ENABLE,ENABLE);
HAL_FDCAN_Start(&FDCAN2_Handler); //开启FDCAN
HAL_FDCAN_ActivateNotification(&FDCAN2_Handler,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
return 0;
}
注意: FDCAN2_Handler.Init.MessageRAMOffset=1280; //信息RAM偏移 /* CAN1和CAN2共享2560个字, 这里CAN1分配前1280字 */ 这里标注里内存地址的偏移量 本文均分了内存 可以根据实际情况分配
引脚分配
//FDCAN1底层驱动,引脚配置,时钟使能
//HAL_FDCAN_Init()调用
//hsdram:FDCAN1句柄
//FDCAN2底层驱动,引脚配置,时钟使能
//HAL_FDCAN_Init()调用
//hsdram:FDCAN1句柄
void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* hfdcan)
{
GPIO_InitTypeDef GPIO_Initure;
RCC_PeriphCLKInitTypeDef FDCAN_PeriphClk;
__HAL_RCC_FDCAN_CLK_ENABLE(); //使能FDCAN1时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); //开启GPIOB时钟
//FDCAN1时钟源配置为PLL1Q
FDCAN_PeriphClk.PeriphClockSelection=RCC_PERIPHCLK_FDCAN;
FDCAN_PeriphClk.FdcanClockSelection=RCC_FDCANCLKSOURCE_PLL;
HAL_RCCEx_PeriphCLKConfig(&FDCAN_PeriphClk);
if(hfdcan == &FDCAN1_Handler)
{
GPIO_Initure.Pin=GPIO_PIN_11|GPIO_PIN_12; //PA11,12
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //推挽复用
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FREQ_MEDIUM; //超高速
GPIO_Initure.Alternate=GPIO_AF9_FDCAN1; //复用为CAN1
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化
HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 2, 0);
HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, 2, 0);
HAL_NVIC_SetPriority(FDCAN_CAL_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn);
HAL_NVIC_EnableIRQ(FDCAN_CAL_IRQn);
}
if(hfdcan == &FDCAN2_Handler)
{
GPIO_Initure.Pin=GPIO_PIN_13|GPIO_PIN_12; //PB13,12
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //推挽复用
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FREQ_MEDIUM; //超高速
GPIO_Initure.Alternate=GPIO_AF9_FDCAN2; //复用为CAN2
HAL_GPIO_Init(GPIOB,&GPIO_Initure); //初始化
HAL_NVIC_SetPriority(FDCAN2_IT0_IRQn, 3, 0);
HAL_NVIC_SetPriority(FDCAN2_IT1_IRQn, 3, 0);
HAL_NVIC_SetPriority(FDCAN_CAL_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(FDCAN2_IT0_IRQn);
HAL_NVIC_EnableIRQ(FDCAN2_IT1_IRQn);
HAL_NVIC_EnableIRQ(FDCAN_CAL_IRQn);
}
}
注意使用CubeMX分配的时候 PA11 PA12引脚会可能分开注意区分
中断服务函数
//FDCAN1中断服务函数
void FDCAN1_IT0_IRQHandler(void)
{
HAL_FDCAN_IRQHandler(&FDCAN1_Handler);
}
void FDCAN2_IT0_IRQHandler(void)
{
HAL_FDCAN_IRQHandler(&FDCAN2_Handler);
}
// void FDCAN1_IT1_IRQHandler(void)
// {
// HAL_FDCAN_IRQHandler(&FDCAN1_Handler);
// }
// void FDCAN2_IT1_IRQHandler(void)
// {
// HAL_FDCAN_IRQHandler(&FDCAN2_Handler);
// }
根据接收的数据分别启动中断服务函数
中断回调函数 数据处理
void FDCAN_CAL_IRQHandler(void) //中断服务函数
{
HAL_FDCAN_IRQHandler(&FDCAN1_Handler);
HAL_FDCAN_IRQHandler(&FDCAN2_Handler);
}
//FIFO0回调函数
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
u8 rxdata[8];
if(hfdcan == &FDCAN1_Handler)
{
if((RxFifo0ITs&FDCAN_IT_RX_FIFO0_NEW_MESSAGE)!=RESET) //FIFO1新数据中断
{
//提取FIFO0中接收到的数据
HAL_FDCAN_GetRxMessage(hfdcan,FDCAN_RX_FIFO0,&FDCAN1_RxHeader,rxdata);
get_can_data(&FDCAN1_RxHeader,rxdata); //解析CAN报文
HAL_FDCAN_ActivateNotification(hfdcan,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
}
}
if(hfdcan == &FDCAN2_Handler)
{
if((RxFifo0ITs&FDCAN_IT_RX_FIFO0_NEW_MESSAGE)!=RESET) //FIFO1新数据中断
{
//提取FIFO0中接收到的数据
HAL_FDCAN_GetRxMessage(hfdcan,FDCAN_RX_FIFO0,&FDCAN2_RxHeader,rxdata);
get_can_data(&FDCAN2_RxHeader,rxdata); //解析CAN报文
HAL_FDCAN_ActivateNotification(hfdcan,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
}
}
}
//接收的数据解析
void get_can_data(FDCAN_RxHeaderTypeDef *pRxHeader,uint8_t *pRxData)//CAN报文解析
{
if(pRxHeader == &FDCAN1_RxHeader)
{
switch (pRxHeader->Identifier)
{
case 0x18FEEE00: //冷却液温度
break;
default:
break;
}
}
if(pRxHeader == &FDCAN2_RxHeader)
{
switch (pRxHeader->Identifier)
{
case 0x18FEEE00: //冷却液温度
break;
default:
break;
}
}
}
发送数据
//can发送一组数据
// FDCAN_HandleTypeDef *hfdcan CAN通道
//ID_Number:数据帧的ID
//ID_type: 数据帧的类型 FDCAN_EXTENDED_ID 扩展帧 FDCAN_STANDARD_ID 标准帧
//ID_frame:数据帧的格式 FDCAN_DATA_FRAME 数据帧 FDCAN_REMOTE_FRAME 远程帧
//msg:数据指针.
//adddr 起始地址
//返回值:0,成功;
// 其他,失败;
u8 FDCAN_Send_Msg(FDCAN_HandleTypeDef *hfdcan,u32 ID_Number,u32 ID_type,u32 ID_frame,u8* msg,u8 adddr)
{
u8 send_data[8];
my_strcpy_addr_array(send_data,msg,adddr,8);
if(hfdcan->Instance==FDCAN1)
{
FDCAN1_TxHeader.Identifier=ID_Number; //32位ID
FDCAN1_TxHeader.IdType=ID_type; //数据帧种类
FDCAN1_TxHeader.TxFrameType=ID_frame; //数据帧类型
FDCAN1_TxHeader.DataLength=(u32)8<<16; //数据长度
FDCAN1_TxHeader.ErrorStateIndicator=FDCAN_ESI_ACTIVE;
FDCAN1_TxHeader.BitRateSwitch=FDCAN_BRS_OFF; //关闭速率切换
FDCAN1_TxHeader.FDFormat=FDCAN_CLASSIC_CAN; //传统的CAN模式
FDCAN1_TxHeader.TxEventFifoControl=FDCAN_NO_TX_EVENTS; //无发送事件
FDCAN1_TxHeader.MessageMarker=0;
if(HAL_FDCAN_AddMessageToTxFifoQ(&FDCAN1_Handler,&FDCAN1_TxHeader,send_data)!=HAL_OK) return 1;//发送
return 0;
}
else if (hfdcan->Instance==FDCAN2)
{
FDCAN2_TxHeader.Identifier=ID_Number; //32位ID
FDCAN2_TxHeader.IdType=ID_type; //数据帧种类
FDCAN2_TxHeader.TxFrameType=ID_frame; //数据帧类型
FDCAN2_TxHeader.DataLength=(u32)8<<16; //数据长度
FDCAN2_TxHeader.ErrorStateIndicator=FDCAN_ESI_ACTIVE;
FDCAN2_TxHeader.BitRateSwitch=FDCAN_BRS_OFF; //关闭速率切换
FDCAN2_TxHeader.FDFormat=FDCAN_CLASSIC_CAN; //传统的CAN模式
FDCAN2_TxHeader.TxEventFifoControl=FDCAN_NO_TX_EVENTS; //无发送事件
FDCAN2_TxHeader.MessageMarker=0;
if(HAL_FDCAN_AddMessageToTxFifoQ(&FDCAN2_Handler,&FDCAN2_TxHeader,send_data)!=HAL_OK) return 1;//发送
return 0;
}
return 0;
}