Files
ranchuan bcbd02a72c V2.13 使用新的can帧回复数据
解决ew自检模式 8导致小板死机的bug,自检返回值除以400,单位0.1ms
2024-01-08 18:04:05 +08:00

427 lines
10 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "stm32f10x.h"
#include "if_can.h"
#include "rtthread.h"
#include "rthw.h"
#include "elec_det.h"
#include "board.h"
#include "core_delay.h"
CanRxMsg receive_message;
static YeCanRxFrame_st canrx_st;
static uint8_t Can_Device_ID = 0;
static uint32_t GetCanFilter(YeCanID_un yeid);
uint32_t ul_exid,ul_can_mask;
rt_mutex_t can_tx_mutex;
volatile uint8_t CAN0_TX_BUSY_Flag = 0;
/*
@brief CAN通讯初始化 包括CANgpio 过滤器
*/
void YeCanInit(void)
{
uint32_t ul_filter,ul_mask;
CAN_InitTypeDef CAN_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
YeCanID_un yeid_un;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//CAN GPIO 初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
CAN_DeInit(CAN1);
CAN_StructInit(&CAN_InitStructure);
CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_ABOM = DISABLE;
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_NART = DISABLE;
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_TXFP = ENABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
if(elec_hard_version()==1){
CAN_InitStructure.CAN_Prescaler = 60;
}else{
CAN_InitStructure.CAN_Prescaler = 30;
}
CAN_Init(CAN1, &CAN_InitStructure);
Can_Device_ID = elec_local_addr();
yeid_un.Exide = 0;
yeid_un.yecanid_old.ACK = 0;
yeid_un.yecanid_old.FunClass = 0;
yeid_un.yecanid_old.Reserve1 = 0;
yeid_un.yecanid_old.Reserve0 = 0;
yeid_un.yecanid_old.SegFlag = 0;
yeid_un.yecanid_old.SegNum = 0;
yeid_un.yecanid_old.srcMACID = 0x00;
yeid_un.yecanid_old.destMACID = 0x1F;
ul_mask = GetCanFilter(yeid_un);
ul_can_mask =ul_mask;
yeid_un.yecanid_old.destMACID = Can_Device_ID;
ul_filter = GetCanFilter(yeid_un);
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = (ul_filter >> 16) & 0x0FFFF;;
CAN_FilterInitStructure.CAN_FilterIdLow = ul_filter & 0x0FFFF;;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = (ul_mask >> 16) & 0x0FFFF;;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = ul_mask & 0x0FFFF; ;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
// yeid_un.yecanid_old.destMACID = 0x1E;
// ul_filter = GetCanFilter(yeid_un);
// CAN_FilterInitStructure.CAN_FilterNumber = 1;
// CAN_FilterInitStructure.CAN_FilterIdHigh = (ul_filter >> 16) & 0x0FFFF;;
// CAN_FilterInitStructure.CAN_FilterIdLow = ul_filter & 0x0FFFF;;
// CAN_FilterInit(&CAN_FilterInitStructure);
yeid_un.yecanid_old.destMACID = 0x1F;
ul_filter = GetCanFilter(yeid_un);
CAN_FilterInitStructure.CAN_FilterNumber = 2;
CAN_FilterInitStructure.CAN_FilterIdHigh = (ul_filter >> 16) & 0x0FFFF;;
CAN_FilterInitStructure.CAN_FilterIdLow = ul_filter & 0x0FFFF;;
CAN_FilterInit(&CAN_FilterInitStructure);
CAN_OperatingModeRequest(CAN1,CAN_OperatingMode_Normal);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
can_tx_mutex = rt_mutex_create ("can0_tx_mutex",RT_IPC_FLAG_PRIO);
}
/*
@brief 根据设置CAN 的ID协议获取帧过滤值
*/
static uint32_t GetCanFilter(YeCanID_un yeid)
{
uint32_t filter = 0;
filter = yeid.Exide << 3;
filter |= 0x04;//只接收扩展帧
filter &= ~((uint32_t)0x003);//不限定帧类型
return filter;
}
/*
@brief CAN发送通讯帧
@param 源地址
@param 主机地址
@param 发送数据缓存
@param 发送数据长度
@rtv 0 成功 1 失败
*/
uint8_t YeCan_SendFrame(uint8_t srcaddr,uint8_t dstaddr,const uint8_t* txdata, uint16_t len,int delay_ms)
{
CanTxMsg transmit_message;
uint8_t mailbox_number;
YeCanID_un yeid_un;
uint32_t time_out = delay_ms*1000;
uint8_t uc_rtv = 0;
uint32_t tick_start=0;
uint8_t pack_len;
tick_start=delay_get_us();
transmit_message.ExtId = 0x00;
transmit_message.StdId = 0x00;
transmit_message.RTR = CAN_RTR_DATA;
transmit_message.IDE = CAN_ID_EXT;
yeid_un.Exide = 0;
yeid_un.yecanid.srcMACID = srcaddr;
yeid_un.yecanid.destMACID = dstaddr;
yeid_un.yecanid.ACK = 0;
yeid_un.yecanid.FunClass = 1;
yeid_un.yecanid.SegFlag = 0;
yeid_un.yecanid.SegNum = 0;
yeid_un.yecanid.Reserve0=1;// 使用新协议
if(len <= 8)
{
transmit_message.DLC = len;
transmit_message.ExtId = yeid_un.Exide;
memcpy(transmit_message.Data,txdata,8);
mailbox_number = CAN_Transmit(CAN1, &transmit_message);
}else{
while(len > 0)
{
pack_len=8;
if(len<pack_len){
pack_len=len;
}
memcpy(transmit_message.Data,txdata,pack_len);
if(yeid_un.yecanid.SegNum == 0){
yeid_un.yecanid.SegFlag = 0x01;
}else if(len>8){
yeid_un.yecanid.SegFlag = 0x02;
}else{
yeid_un.yecanid.SegFlag = 0x03;
}
len -= pack_len;
txdata += pack_len;
transmit_message.DLC = pack_len;
transmit_message.ExtId = yeid_un.Exide;
while(mailbox_number = CAN_Transmit(CAN1, &transmit_message),mailbox_number==CAN_TxStatus_NoMailBox)
//while( CAN_TxStatus_Ok != CAN_TransmitStatus(CAN1,mailbox_number))
{
rt_hw_us_delay(20);
if(delay_check(tick_start,time_out))
{
uc_rtv = 1;
goto can0_tx_end;
}
}
yeid_un.yecanid.SegNum ++;
}
}
can0_tx_end:
CAN0_TX_BUSY_Flag = 0;
return uc_rtv;
}
typedef struct{
void (*end_irq)(void *t,uint32_t len);
void *t;
uint32_t rx_buff_size;
}self_def;
static self_def g_self;
static void save_data(void)
{
YeCanID_un yeid_un;
uint8_t seg,seg_num,dstaddr;
yeid_un.Exide = receive_message.ExtId;
ul_exid = yeid_un.Exide << 3;
ul_exid &= ul_can_mask;
if(yeid_un.yecanid.Reserve0==0){
seg=yeid_un.yecanid_old.SegFlag;
seg_num=yeid_un.yecanid_old.SegNum;
dstaddr=yeid_un.yecanid_old.destMACID;
}else{
seg=yeid_un.yecanid.SegFlag;
seg_num=yeid_un.yecanid.SegNum;
dstaddr=yeid_un.yecanid.destMACID;
}
if((dstaddr!=elec_local_addr())&&(dstaddr!=0x1f)){
return;
}
if(receive_message.DLC > 0)
{
if(seg == 00)
{
memcpy(canrx_st.rx_databuf,receive_message.Data,receive_message.DLC);
canrx_st.rx_index = receive_message.DLC;
g_self.end_irq(g_self.t,canrx_st.rx_index);
}
else if(seg == 0x01)
{
canrx_st.seg_num = 0;
memcpy(canrx_st.rx_databuf,receive_message.Data,receive_message.DLC);
canrx_st.rx_index = receive_message.DLC;
}else if(seg == 0x02)
{
if((canrx_st.seg_num+1) == seg_num )
{
canrx_st.seg_num++;
memcpy(canrx_st.rx_databuf+canrx_st.rx_index,receive_message.Data,receive_message.DLC);
canrx_st.rx_index += receive_message.DLC;
}else{
//error
}
}else if(seg == 0x03)
{
memcpy(canrx_st.rx_databuf+canrx_st.rx_index,receive_message.Data,receive_message.DLC);
canrx_st.rx_index += receive_message.DLC;
g_self.end_irq(g_self.t,canrx_st.rx_index);
}
}
}
void USB_LP_CAN1_RX0_IRQHandler(void)
{
rt_interrupt_enter();
CAN_Receive(CAN1, CAN_FIFO0, &receive_message);
if(g_self.end_irq&&canrx_st.rx_databuf){
save_data();
}
CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);
rt_interrupt_leave();
}
static int init(uart_def *u,int bsp)
{
YeCanInit();
return 0;
}
static int deinit(uart_def *u)
{
return 0;
}
static int set_irq(uart_def *u,void (*irq)(void *t,uint8_t d),void *t)
{
return 0;
}
static int set_end_irq(uart_def *u,uint8_t *rx_buff,int rx_buff_size,
void (*irq)(void *t,uint32_t len),void *t)
{
irq_disable();
g_self.end_irq=irq;
canrx_st.rx_databuf=rx_buff;
g_self.rx_buff_size=rx_buff_size;
g_self.t=t;
irq_enable();
return 0;
}
static int read(uart_def *u,uint8_t *b,int len)
{
return 0;
}
static int write(uart_def *u,const uint8_t *b,int len,int timeout_ms)
{
uint8_t src=elec_local_addr();
uint8_t dst=0;
uint8_t ret;
ret=YeCan_SendFrame(src,dst,b,len,timeout_ms);
if(ret==0) return len;
else return 0;
}
uart_init_export(can,init,deinit,set_irq,set_end_irq,read,write,0)
typedef struct{
uart_def *dev[2];
int dev_index;
int inited;
void (*end_irq)(void *t,uint32_t len);
void *t;
}h_self_def;
static h_self_def g_hself;
static int h_init(uart_def *u,int bsp)
{
h_self_def *h=&g_hself;
if(h->inited) return 0;
// 设置主机接口 int类型0uart1can
app_variable("host_if",&h->dev_index,0);
h->dev[0]=dev_get("uart1");
h->dev[1]=dev_get("can");
h->dev[0]->init(h->dev[0],0);
h->dev[1]->init(h->dev[1],0);
return 0;
}
static int h_deinit(uart_def *u)
{
return 0;
}
static int h_set_irq(uart_def *u,void (*irq)(void *t,uint8_t d),void *t)
{
return 0;
}
static void h_end_irq0(void *t,uint32_t len)
{
h_self_def *h=&g_hself;
h->dev_index=0;
if(h->end_irq)
{
h->end_irq(h->t,len);
}
}
static void h_end_irq1(void *t,uint32_t len)
{
h_self_def *h=&g_hself;
h->dev_index=1;
if(h->end_irq)
{
h->end_irq(h->t,len);
}
}
static int h_set_end_irq(uart_def *u,uint8_t *rx_buff,int rx_buff_size,
void (*irq)(void *t,uint32_t len),void *t)
{
h_self_def *h=&g_hself;
irq_disable();
h->end_irq=irq;
h->t=t;
irq_enable();
h->dev[0]->set_end_irq(h->dev[0],rx_buff,rx_buff_size,h_end_irq0,h);
h->dev[1]->set_end_irq(h->dev[1],rx_buff,rx_buff_size,h_end_irq1,h);
return 0;
}
static int h_read(uart_def *u,uint8_t *b,int len)
{
return 0;
}
static int h_write(uart_def *u,const uint8_t *b,int len,int timeout_ms)
{
h_self_def *h=&g_hself;
uart_def *s=h->dev[h->dev_index];
return s->write(s,b,len,timeout_ms);
}
uart_init_export(host,h_init,h_deinit,h_set_irq,h_set_end_irq,h_read,h_write,0)