438 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			438 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#include "if_can.h"
 | 
						||
#include "rtthread.h"
 | 
						||
#include "rthw.h"
 | 
						||
#include "elec_det.h"
 | 
						||
#include "board.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;
 | 
						||
	CAN_InitStructure.CAN_Prescaler = 30;
 | 
						||
 | 
						||
	CAN_Init(CAN1, &CAN_InitStructure);
 | 
						||
 | 
						||
	Can_Device_ID = elec_local_addr();
 | 
						||
	
 | 
						||
	yeid_un.Exide = 0;
 | 
						||
	yeid_un.yecanid.ACK = 0;
 | 
						||
	yeid_un.yecanid.FunClass = 0;
 | 
						||
	yeid_un.yecanid.Reserve1 = 0;
 | 
						||
	yeid_un.yecanid.Reserve0 = 0;
 | 
						||
	yeid_un.yecanid.SegFlag = 0;
 | 
						||
	yeid_un.yecanid.SegNum = 0;
 | 
						||
	yeid_un.yecanid.srcMACID = 0x00;
 | 
						||
	
 | 
						||
	yeid_un.yecanid.destMACID = 0x1F;
 | 
						||
	ul_mask = GetCanFilter(yeid_un);
 | 
						||
	ul_can_mask =ul_mask;
 | 
						||
	yeid_un.yecanid.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.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.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)
 | 
						||
{
 | 
						||
	CanTxMsg  transmit_message;
 | 
						||
	uint8_t mailbox_number;
 | 
						||
	YeCanID_un yeid_un;
 | 
						||
	uint32_t time_out = 0;
 | 
						||
	uint8_t uc_rtv = 0;
 | 
						||
	//can_transmission_stop(CAN1,0);
 | 
						||
	/* initialize transmit message */
 | 
						||
	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;
 | 
						||
	if(srcaddr == 0x00 || srcaddr == 0x1f)
 | 
						||
	{
 | 
						||
		time_out = 0;
 | 
						||
		while(time_out < 5)
 | 
						||
		{
 | 
						||
			elec_led1_power(0);
 | 
						||
			rt_thread_mdelay(50);
 | 
						||
			elec_led1_power(1);
 | 
						||
			rt_thread_mdelay(50);
 | 
						||
			time_out++;
 | 
						||
			
 | 
						||
		}
 | 
						||
	}
 | 
						||
	if(can_tx_mutex != RT_NULL)
 | 
						||
	{
 | 
						||
		if(RT_EOK != rt_mutex_take (can_tx_mutex,500))
 | 
						||
		{
 | 
						||
			return 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);
 | 
						||
		time_out = 5000;
 | 
						||
		while( CAN_TxStatus_Ok != CAN_TransmitStatus(CAN1,mailbox_number) && time_out > 0)
 | 
						||
		{
 | 
						||
			time_out --;
 | 
						||
			rt_hw_us_delay(20);
 | 
						||
		}
 | 
						||
		if(time_out == 0)
 | 
						||
		{
 | 
						||
			uc_rtv = 1;
 | 
						||
			goto can0_tx_end;
 | 
						||
		}
 | 
						||
		goto can0_tx_end;
 | 
						||
	}
 | 
						||
	while(len > 8)
 | 
						||
	{
 | 
						||
		memcpy(transmit_message.Data,txdata,8);
 | 
						||
		len -= 8;
 | 
						||
		txdata += 8;
 | 
						||
		
 | 
						||
		if(yeid_un.yecanid.SegNum == 0)
 | 
						||
		{
 | 
						||
			yeid_un.yecanid.SegFlag = 0x01;
 | 
						||
		}else 
 | 
						||
		{
 | 
						||
			yeid_un.yecanid.SegFlag = 0x02;
 | 
						||
		}
 | 
						||
		transmit_message.ExtId = yeid_un.Exide;
 | 
						||
		transmit_message.DLC = 8;
 | 
						||
		mailbox_number = CAN_Transmit(CAN1, &transmit_message);
 | 
						||
		time_out = 5000;
 | 
						||
		while( CAN_TxStatus_Ok != CAN_TransmitStatus(CAN1,mailbox_number) && time_out > 0)
 | 
						||
		{
 | 
						||
			time_out --;
 | 
						||
			rt_hw_us_delay(20);
 | 
						||
		}
 | 
						||
		if(time_out == 0)
 | 
						||
		{
 | 
						||
			uc_rtv = 1;
 | 
						||
			goto can0_tx_end;
 | 
						||
		}
 | 
						||
		yeid_un.yecanid.SegNum ++;
 | 
						||
	}
 | 
						||
	yeid_un.yecanid.SegFlag = 0x3;
 | 
						||
	memcpy(transmit_message.Data,txdata,len);
 | 
						||
  transmit_message.DLC = len;
 | 
						||
	transmit_message.ExtId = yeid_un.Exide;
 | 
						||
	mailbox_number = CAN_Transmit(CAN1, &transmit_message);
 | 
						||
	time_out = 5000;
 | 
						||
	while(CAN_TxStatus_Ok != CAN_TransmitStatus(CAN1,mailbox_number) && time_out > 0)
 | 
						||
	{
 | 
						||
		
 | 
						||
		time_out --;
 | 
						||
		rt_hw_us_delay(20);
 | 
						||
	}
 | 
						||
	if(time_out == 0)
 | 
						||
	{
 | 
						||
		
 | 
						||
		uc_rtv = 1;
 | 
						||
	}
 | 
						||
	
 | 
						||
can0_tx_end:
 | 
						||
	CAN0_TX_BUSY_Flag = 0;
 | 
						||
	rt_mutex_release(can_tx_mutex);
 | 
						||
	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;
 | 
						||
	if(receive_message.DLC > 0)
 | 
						||
	{
 | 
						||
		yeid_un.Exide = receive_message.ExtId;
 | 
						||
		ul_exid = 	yeid_un.Exide << 3;
 | 
						||
		ul_exid &= ul_can_mask;
 | 
						||
		if(yeid_un.yecanid.SegFlag == 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(yeid_un.yecanid.SegFlag == 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(yeid_un.yecanid.SegFlag == 0x02)
 | 
						||
		{
 | 
						||
			if((canrx_st.seg_num+1) == yeid_un.yecanid.SegNum )
 | 
						||
			{
 | 
						||
				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(yeid_un.yecanid.SegFlag == 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)
 | 
						||
{
 | 
						||
  uint8_t src=b[4];
 | 
						||
  uint8_t dst=b[5];
 | 
						||
  uint8_t ret;
 | 
						||
  ret=YeCan_SendFrame(src,dst,b,len);
 | 
						||
  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类型,0uart,1can
 | 
						||
  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)
 | 
						||
{
 | 
						||
  h_self_def *h=&g_hself;
 | 
						||
  uart_def *s=h->dev[h->dev_index];
 | 
						||
  return s->write(s,b,len);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
uart_init_export(host,h_init,h_deinit,h_set_irq,h_set_end_irq,h_read,h_write,0)
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 |