打印
[应用相关]

我也上传一些自己收藏的 can 总线方面的资料!

[复制链接]
2408|28
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
STM32 CAN总线调试的一点心得总结

一. 开发平台与工具:

1. 平台: STM32F103C8T6  48PIN工控板和自己设计的STM32开发板

2. 软件: MDK5 UVision V5.14.0.0

3. PACK: STM32F1xx_DFP——1.0.5(2014-03-14)

4. 其它:USB转串口,ST-Link下载器,

USB-CAN Adapter(比较便宜的购买

用于直接监视CAN口发出的数据,上位机有两个,一个是EmbededConfig for USB2CAN 配置串口、串口波特率、CAN速率等,另一个是EmbededDebug V2.0监视CAN口数据;使用顺序是先配置后查看CAN数据。



沙发
wangjiahao88|  楼主 | 2018-8-22 14:55 | 只看该作者
二. CAN总线的介绍简略:

bxCAN 是基本扩展 CAN (Basic Extended CAN) 的缩写,它支持 CAN 协议 2.0A 和 2.0B 。它的设计目标是,以最小的 CPU 负荷来高效处理大量收到的报文。它也支持报文发送的优先级要求(优先级特性可软件配置)。

对于安全紧要的应用,bxCAN 提供所有支持时间触发通信模式所需的硬件功能。

使用特权

评论回复
板凳
wangjiahao88|  楼主 | 2018-8-22 14:56 | 只看该作者
主要特点
· 支持 CAN 协议 2.0A 和 2.0B 主动模式
· 波特率最高可达 1 兆位 / 秒
· 支持时间触发通信功能

使用特权

评论回复
地板
wangjiahao88|  楼主 | 2018-8-22 14:56 | 只看该作者
发送
· 3 个发送邮箱
· 发送报文的优先级特性可软件配置
· 记录发送 SOF 时刻的时间戳

使用特权

评论回复
5
wangjiahao88|  楼主 | 2018-8-22 14:56 | 只看该作者
接收
· 3 级深度的2个接收 FIFO
· 14 个位宽可变的过滤器组 - 由整个 CAN 共享
· 标识符列表
· FIFO 溢出处理方式可配置
· 记录接收 SOF 时刻的时间戳

可支持时间触发通信模式
· 禁止自动重传模式
· 16 位自由运行定时器
· 定时器分辨率可配置
· 可在最后 2 个数据字节发送时间戳

管理
· 中断可屏蔽
· 邮箱占用单独 1 块地址空间,便于提高软件效率

使用特权

评论回复
6
wangjiahao88|  楼主 | 2018-8-22 14:57 | 只看该作者
遇到的问题分析与解决:
手上有两块STM32的板子,一个是网上买的MINI STM32工控板,另一个是自己公司设计的板子。二者有所不同,大致有两点,第一是串口,工控板用的是USART1 且用的是GPIO PA9(TX)和PA10(RX),自设板用的是USART2 且用的是GPIO PA2(TX)和PA3(RX);第二是CAN口管脚不同,工控板用的是复用功能映射到PB8(RX)和PB9(TX),而自设板用的是PA11(RX)和PA12(TX)。下图所示,两块板子部分原理图:


使用特权

评论回复
7
wangjiahao88|  楼主 | 2018-8-22 14:58 | 只看该作者
现在我是在工控板测试代码基础上,用到自设板上,实现PC端串口与STM32 CAN双向通信,要做的是将USART和CAN口的GPIO配置对应到自设板上。

首先,串口GPIO配置:

void USART1_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;

        /* config USART1 clock */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
       
        /* USART1 GPIO config */
   /* Configure USART1 Tx (PA.09) as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);   
  /* Configure USART1 Rx (PA.10) as input floating */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
          
        /* USART1 mode config */
        USART_InitStructure.USART_BaudRate = 115200;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No ;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        USART_Init(USART1, &USART_InitStructure);
  USART_Cmd(USART1, ENABLE);
       
        /* Enable the EVAL_COM1 Transmit interrupt: this interrupt is generated when the
     EVAL_COM1 transmit data register is empty */  
  //USART_ITConfig(USART1, USART_IT_TXE, ENABLE);

  /* Enable the EVAL_COM1 Receive interrupt: this interrupt is generated when the
     EVAL_COM1 receive data register is not empty */
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
}

/***************USART1 ÅäÖÃÖжϷ½Ê½·¢ËͽÓÊÕÊý¾Ý******************************/
void USART1_NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable the USARTx Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

/****************USART1 ÖжϺ¯Êý***************************/
void USART1_IRQHandler(void)
{
        if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
        {
                RxBuffer[RxCounter++] = (USART_ReceiveData(USART1));
        }
}

使用特权

评论回复
8
wangjiahao88|  楼主 | 2018-8-22 14:58 | 只看该作者
USART1_Config()用于USART1的GPIO配置,配置到
*          | PA9  - USART1(Tx)      |
*          | PA10 - USART1(Rx)      |
*           ------------------------
USART1_NVIC_Configuration() 用于USART1设置中断方式接受发送数据

USART1_IRQHandler()用于USART1中断接受函数

使用特权

评论回复
9
wangjiahao88|  楼主 | 2018-8-22 14:58 | 只看该作者
自设板

void USART2_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;

        /* config USART2 clock */
        //RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 , ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
       
        /* USART2 GPIO config */
   /* Configure USART2 Tx (PA.02) as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);   
  /* Configure USART2 Rx (PA.03) as input floating */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
          
        /* USART2 mode config */
        USART_InitStructure.USART_BaudRate = 115200;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No ;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        USART_Init(USART2, &USART_InitStructure);
        USART_Cmd(USART2, ENABLE);
       
        /* Enable the EVAL_COM1 Transmit interrupt: this interrupt is generated when the
     EVAL_COM1 transmit data register is empty */  
  //USART_ITConfig(USART1, USART_IT_TXE, ENABLE);

  /* Enable the EVAL_COM1 Receive interrupt: this interrupt is generated when the
     EVAL_COM1 receive data register is not empty */
  //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
        USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
}


/***************USART2 ÅäÖÃÖжϷ½Ê½·¢ËͽÓÊÕÊý¾Ý******************************/
void USART2_NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable the USARTx Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

/****************USART2 ÖжϺ¯Êý***************************/
void USART2_IRQHandler(void)
{
        if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
        {
                RxBuffer[RxCounter++] = (USART_ReceiveData(USART2));
        }
}

使用特权

评论回复
10
wangjiahao88|  楼主 | 2018-8-22 14:59 | 只看该作者
USART2_Config()用于USART2的GPIO配置,配置到
*          | PA2  - USART2(Tx)      |
*          | PA3 - USART2(Rx)      |
*           ------------------------

USART2_NVIC_Configuration() 用于USART2设置中断方式接受发送数据

USART2_IRQHandler()用于USART2中断接受函数

使用特权

评论回复
11
wangjiahao88|  楼主 | 2018-8-22 14:59 | 只看该作者
工控板,然后,配置CAN口GPIO

/*CAN GPIO ºÍʱÖÓÅäÖà */
void CAN_GPIO_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  /* ¸´Óù¦ÄܺÍGPIOB¶Ë¿ÚʱÖÓʹÄÜ*/         
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE);                                                                                                                         

  /* CAN1 Ä£¿éʱÖÓʹÄÜ */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

  /* Configure CAN pin: RX */         // PB8
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;         // ÉÏÀ­ÊäÈë
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  
  /* Configure CAN pin: TX */   // PB9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // ¸´ÓÃÍÆÍìÊä³ö
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  
        //#define GPIO_Remap_CAN    GPIO_Remap1_CAN1 ±¾ÊµÑéûÓÐÓõ½ÖØÓ³ÉäI/O
  GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);

  
}

使用特权

评论回复
12
wangjiahao88|  楼主 | 2018-8-22 14:59 | 只看该作者
自设板

void CAN_GPIOA_Config(void)  
{  
GPIO_InitTypeDef GPIO_InitStructure;     
/* CAN Periph clock enable */  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);  
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);  
  
  /* Configure CAN pin: TX */  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;  
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
  GPIO_Init(GPIOA, &GPIO_InitStructure);     
/* Configure CAN pin: RX */  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   
  GPIO_Init(GPIOA, &GPIO_InitStructure);     
  //GPIO_PinRemapConfig(GPIO_Remap1_CAN1 , ENABLE);  
}

使用特权

评论回复
13
wangjiahao88|  楼主 | 2018-8-22 15:00 | 只看该作者
出现几个小问题,但是却是致命的问题:

第一配置GPIO_Speed:

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  //配置GPIO_Speed为50MHz
如果配置GPIO时,省略这一步,会导致CAN口发送不出数据,工控板的配置是放在LED 的GPIO配置中,一开始忽略了这一点,之后用排除法试出来的;

使用特权

评论回复
14
wangjiahao88|  楼主 | 2018-8-22 15:00 | 只看该作者
第二配置复用功能和映射与否:

// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //复用功能时钟使能
//GPIO_PinRemapConfig(GPIO_Remap1_CAN1 , ENABLE); //重映射I/O CAN使能

上面两个被注释掉了,是由于:
用PA11和PA12 用的是CAN的默认端口,而用PB8和PB9是用CAN的复用功能重映射端口。

使用特权

评论回复
15
wangjiahao88|  楼主 | 2018-8-22 15:01 | 只看该作者


默认模式

   /* Configure CAN pin: RX */

  

GPIO

_InitStructure.GPIO_Pin = GPIO_Pin_11;

   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;

   GPIO_Init(GPIOA, &GPIO_InitStructure);

  

   /* Configure CAN pin: TX */

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;

   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

   GPIO_Init(GPIOA, &GPIO_InitStructure);

------------------------------------------------------------------------

使用特权

评论回复
16
wangjiahao88|  楼主 | 2018-8-22 15:01 | 只看该作者
重定义地址1模式

/* Configure CAN pin: RX */

   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;

   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;

   //GPIO_Init(GPIOB, &GPIO_InitStructure);

   /* Configure CAN pin: TX */  

   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

   //GPIO_Init(GPIOB, &GPIO_InitStructure);

   /* Configure CAN Remap   重影射 */

   //GPIO_PinRemapConfig(GPIO_Remap1_CAN, ENABLE);

-------------------------------------------------------------------------  

使用特权

评论回复
17
wangjiahao88|  楼主 | 2018-8-22 15:01 | 只看该作者
重定义地址2模式

   /* Configure CAN pin: RX */

   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;

   //GPIO_Init(GPIOD, &GPIO_InitStructure);

  

   /* Configure CAN pin: TX */

   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

   //GPIO_Init(GPIOD, &GPIO_InitStructure);

  

   /* Configure CAN Remap   重影射 */

   //GPIO_PinRemapConfig(GPIO_Remap2_CAN, ENABLE);

-------------------------------------------------------------------------

使用特权

评论回复
18
wangjiahao88|  楼主 | 2018-8-22 15:02 | 只看该作者
一开始对CAN硬件部分没有过多的了解,后面经过一系列的试验,发现:

1. 如果STM32 CAN TX和RX没有和CAN收发器连接的情况下,STM32的CAN TX和RX是没用数据发出的;

2. STM32 CAN TX和RX必须要与CAN收发器的TX和RX对应,即TX接TX,RX接RX,否则CAN没有数据发出,说明:之所以说这个问题,不知道你们有没有注意到,我的自设板CAN收发器TX和RX是反接的;

3. STM32F103C8T6-LQFP48 的CAN口和USB口复用,即用CAN口是需要将USB口断开,防止有所影响;

4. 是我本身设备问题,我的自设板用的12V电源是我自己焊接的,不太可靠,电源12V时有时无的,所以最好烧写程序的时候点亮一个LED灯,可以显示板子的工作状态;

5. 工控板上CAN收发器是用TJA1050 是5V供电的,自设板用SN65HVD234 3.3-V CAN Bus Transceivers,之前有所顾虑,怕CAN收发器不一样会导致其它后果,之后发现没有问题。

使用特权

评论回复
19
wangjiahao88|  楼主 | 2018-8-22 15:10 | 只看该作者
#include "stm32f10x.h"
例程

#include "stm32f10x.h"
#include "main.h"
#include "CAN.h"  
#include "SCI.H"
#include "led.h"
#include "delay.h"
#include "GPIO.h"


void NVIC_Configuration(void);
void USART_Configuration(void);
u8 can1[8]={0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01};
u8 can2[8]={0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02};
u8 can3[8]={0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03};
u8 can4[8]={0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04};
u8 can5[8]={0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05};
u8 can6[8]={0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06};
u8 can7[8]={0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
u8 can8[8]={0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08};
u8 can9[8]={0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09};
u8 t;
u8 i;
u8 can2_num;
unsigned char CAN2_BUF[100];
int main(void)
{
       
        /* Setup STM32 system (clocks, GPIO, NVIC) */
        System_Setup();
    NVIC_Configuration();
    USART_Configuration();
        GPIO_Configuration();
        CAN_Configuration();
        LED_Init();
        delay_init(72);  
       
        while (1)
        {

       

                if(can1_rec_flag == 1)//收到数据后发送6帧数据上去
                        {
                        can1_rec_flag = 0;
                        CAN1_Send_Msg(can1,8,CAN1_ID);
                        CAN1_Send_Msg(can2,8,CAN1_ID);
                        CAN1_Send_Msg(can3,8,CAN1_ID);
                        delay_ms(1);
                        CAN1_Send_Msg(can4,8,CAN1_ID);
                        CAN1_Send_Msg(can5,8,CAN1_ID);
                        CAN1_Send_Msg(can6,8,CAN1_ID);
                                       
                        }
                if(can2_rec_flag == 1)//收到数据后发送3帧数据上去
                {
                        can2_rec_flag = 0;
                        CAN2_Send_Msg(can7,8,CAN2_ID);       
                        CAN2_Send_Msg(can8,8,CAN2_ID);
                        CAN2_Send_Msg(can9,8,CAN2_ID);                       
                }

        }
}

#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {}
}
#endif


/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/

使用特权

评论回复
20
wangjiahao88|  楼主 | 2018-8-22 15:10 | 只看该作者
/***********************************************************************
文件名称:CAN.C
功    能:
编写时间:2012.11.22
编 写 人:
注    意:
***********************************************************************/

#include "CAN.h"
#include "stm32f10x.h"


unsigned char can1_rec_flag = 0;
unsigned char can2_rec_flag = 0;
unsigned char CAN1_DATA[8];
unsigned char CAN2_DATA[8];

unsigned char CAN3_DATA[8]= {0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02};
unsigned char CAN4_DATA[8]= {0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03};
//CAN总线的波特率=PCLK1/((CAN_SJW +CAN_BS1 +  CAN_BS2)*CAN_Prescaler)
//格式: 波特率  CAN_SJW         CAN_BS1  CAN_BS2 CAN_Prescaler
const unsigned int CAN_baud_table[CAN_BAUD_NUM][5] =
{
//波特率, CAN_SJW,   CAN_BS1,    CAN_BS2,CAN_Prescaler
    {5,   CAN_SJW_1tq,CAN_BS1_13tq,CAN_BS2_2tq,450},                //未通
    {10,  CAN_SJW_1tq,CAN_BS1_6tq,CAN_BS2_2tq, 400},                //未通
    {15,  CAN_SJW_1tq,CAN_BS1_13tq,CAN_BS2_2tq,150},                //15K
    {20,  CAN_SJW_1tq,CAN_BS1_6tq, CAN_BS2_2tq,200},                //20k
    {25,  CAN_SJW_1tq,CAN_BS1_13tq,CAN_BS2_2tq,90},                        //25k
    {40,  CAN_SJW_1tq,CAN_BS1_6tq, CAN_BS2_2tq,100},                //40k
    {50,  CAN_SJW_1tq,CAN_BS1_13tq,CAN_BS2_2tq,45},                        //50k
    {62,  CAN_SJW_1tq,CAN_BS1_13tq,CAN_BS2_2tq,36},                        //62.5k
    {80,  CAN_SJW_1tq,CAN_BS1_6tq, CAN_BS2_2tq,50},                        //80k
    {100, CAN_SJW_1tq,CAN_BS1_5tq, CAN_BS2_2tq,45},                        //100K
    {125, CAN_SJW_1tq,CAN_BS1_13tq, CAN_BS2_2tq,18},                //125K
    {200, CAN_SJW_1tq,CAN_BS1_6tq, CAN_BS2_2tq,20},                        //200K
    {250, CAN_SJW_1tq,CAN_BS1_13tq,CAN_BS2_2tq,9},                    //250k
    {400, CAN_SJW_1tq,CAN_BS1_6tq, CAN_BS2_2tq,10},                        //400K
    {500, CAN_SJW_1tq,CAN_BS1_5tq, CAN_BS2_2tq,9},                        //500K
    {666, CAN_SJW_1tq,CAN_BS1_5tq, CAN_BS2_2tq,8},                        //未通
    {800, CAN_SJW_1tq,CAN_BS1_6tq, CAN_BS2_2tq,5},                        //800K
    {1000,CAN_SJW_1tq,CAN_BS1_6tq, CAN_BS2_2tq,4},                        //1000K
};
void CAN_Configuration(void)
{

    CAN_InitTypeDef        CAN_InitStructure;
    CAN_FilterInitTypeDef  CAN_FilterInitStructure;


/////////can1初始///////////////////////////////////


    CAN_DeInit(CAN1);  //将CAN1的全部寄存器重设为缺省值

    CAN_StructInit(&CAN_InitStructure);

    /* CAN cell init */           //can单元设置
    CAN_InitStructure.CAN_TTCM = DISABLE; /* 时间触发禁止, 时间触发:CAN硬件的内部定时器被激活,并且被用于产生时间戳 */
    CAN_InitStructure.CAN_ABOM = DISABLE; /* 自动离线禁止,自动离线:一旦硬件监控到128次11个隐性位,就自动退出离线状态。在这里要软件设定后才能退出 */
    CAN_InitStructure.CAN_AWUM = DISABLE; /* 自动唤醒禁止,有报文来的时候自动退出休眠        */
    CAN_InitStructure.CAN_NART = DISABLE; /* 报文重传, 如果错误一直传到成功止,否则只传一次 */
    CAN_InitStructure.CAN_RFLM = DISABLE; /* 接收FIFO锁定, 1--锁定后接收到新的报文摘不要,0--接收到新的报文则覆盖前一报文        */
    CAN_InitStructure.CAN_TXFP = ENABLE;  /* 发送优先级  0---由标识符决定  1---由发送请求顺序决定        */
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; /* 模式        */


    CAN_Baud_Process(500,&CAN_InitStructure);//波特率500K

    if (CAN_Init(CAN1,&CAN_InitStructure) == CANINITFAILED)
    {

        /* 初始化时先设置CAN_MCR的初始化位 */
        /* 然后查看硬件是否真的设置了CAN_MSR的初始化位来确认是否进入了初始化模式  */
    }
    CAN_FilterInitStructure.CAN_FilterNumber = 0;     ///* 过滤器组 */
    CAN_FilterInitStructure.CAN_FilterMode =CAN_FilterMode_IdList;//CAN_FilterMode_IdList;//CAN_FilterMode_IdMask;  /* 屏敝模式 */
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; ///* 32位 */
    CAN_FilterInitStructure.CAN_FilterIdHigh = 0x2220;  //32为id  0x11
    CAN_FilterInitStructure.CAN_FilterIdLow = 0;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0;//32位mask
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;  ///* 能够通过该过滤器的报文存到fifo0中 */
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);

    CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE);   /* 挂号中断, 进入中断后读fifo的报文函数释放报文清中断标志 */
/////////can2初始///////////////////////////////////

    CAN_DeInit(CAN2);
    CAN_StructInit(&CAN_InitStructure);

    /* CAN cell init */
    CAN_InitStructure.CAN_TTCM = DISABLE; /* 时间触发禁止, 时间触发:CAN硬件的内部定时器被激活,并且被用于产生时间戳 */
    CAN_InitStructure.CAN_ABOM = DISABLE; /* 自动离线禁止,自动离线:一旦硬件监控到128次11个隐性位,就自动退出离线状态。在这里要软件设定后才能退出 */
    CAN_InitStructure.CAN_AWUM = DISABLE; /* 自动唤醒禁止,有报文来的时候自动退出休眠        */
    CAN_InitStructure.CAN_NART = DISABLE; /* 报文重传, 如果错误一直传到成功止,否则只传一次 */
    CAN_InitStructure.CAN_RFLM = DISABLE; /* 接收FIFO锁定, 1--锁定后接收到新的报文摘不要,0--接收到新的报文则覆盖前一报文        */
    CAN_InitStructure.CAN_TXFP = ENABLE;  /* 发送优先级  0---由标识符决定  1---由发送请求顺序决定        */
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; /* 模式        */


    CAN_Baud_Process(500,&CAN_InitStructure);//波特率500K

    if (CAN_Init(CAN2,&CAN_InitStructure) == CANINITFAILED)
    {

        /* 初始化时先设置CAN_MCR的初始化位 */
        /* 然后查看硬件是否真的设置了CAN_MSR的初始化位来确认是否进入了初始化模式  */
    }
    CAN_FilterInitStructure.CAN_FilterNumber = 14;     ///* 过滤器组 */
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;//CAN_FilterMode_IdList;//CAN_FilterMode_IdMask;  /* 屏敝模式 */
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; ///* 32位 */
    CAN_FilterInitStructure.CAN_FilterIdHigh = 0x2240;  //0x12
    CAN_FilterInitStructure.CAN_FilterIdLow = 0;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;  ///* 能够通过该过滤器的报文存到fifo0中 */
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);

    CAN_ITConfig(CAN2,CAN_IT_FMP0, ENABLE);   /* 挂号中断, 进入中断后读fifo的报文函数释放报文清中断标志 */

}

/***********************************************************************
文件名称:CAN_Baud_Process
功    能:计算波特率,返回
编写时间:2013.4.25
编 写 人:
注    意:
CAN_SJW : CAN_SJW_1tq - CAN_SJW_4tq          不能比任何一相位缓冲段长
CAN_BS1 : CAN_BS1_1tq - CAN_BS1_16tq
CAN_BS2 : CAN_BS2_1tq - CAN_BS2_8tq
CAN_Prescaler : 1 - 1024
        配置说明:
CAN_SJW + CAN_BS1 / (CAN_SJW + CAN_BS1 + CAN_BS2)
        0.75     baud > 800k
        0.80     baud > 500k
        0.875    baud <= 500k
        baud = 36 / (CAN_SJW + CAN_BS1 + CAN_BS2) / CAN_Prescaler
***********************************************************************/
void CAN_Baud_Process(unsigned int Baud,CAN_InitTypeDef *CAN_InitStructure)
{
    unsigned int i = 0;
    for(i = 0; i < CAN_BAUD_NUM; i ++)
    {
        if(Baud == CAN_baud_table[i][0])
        {
            CAN_InitStructure->CAN_SJW = CAN_baud_table[i][1];
            CAN_InitStructure->CAN_BS1 = CAN_baud_table[i][2];
            CAN_InitStructure->CAN_BS2 = CAN_baud_table[i][3];
            CAN_InitStructure->CAN_Prescaler = CAN_baud_table[i][4];
            break;
        }
    }
}



u8 CAN1_Send_Msg(u8* msg,u8 len,u16 ID)
{
    u8 mbox;
    u16 i=0;
    CanTxMsg TxMessage;
    TxMessage.StdId=ID;         // 标准标识符11位
    TxMessage.ExtId=ID;         // 设置扩展标示符(29位)
    TxMessage.IDE=CAN_ID_STD;                  // 1使用扩展标识符,0使用标准标识符
    TxMessage.RTR=CAN_RTR_DATA;                  // 消息类型为数据帧,一帧8位
    TxMessage.DLC=len;                                                         // 发送两帧信息
    for(i=0; i<len; i++)
        TxMessage.Data[i]=msg[i];                                 // 第一帧信息
    mbox= CAN_Transmit(CAN1, &TxMessage);
    i=0;
    while((CAN_TransmitStatus(CAN1, mbox)==CANTXFAILED)&&(i<0XFFF))i++;        //等待发送结束
    if(i>=0XFFF)return 1;
    return 0;

}
//CAN1中断程序
void CAN1_RX0_IRQHandler(void)
{
    CanRxMsg RxMessage;
    unsigned char i;

    CAN_Receive(CAN1,CAN_FIFO0, &RxMessage);  /* 此函数包含释放提出报文了的,在非必要时,不需要自己释放 */
    for(i = 0; i < 8; i ++)
    {
        CAN1_DATA[i] = RxMessage.Data[i];
    }
    can1_rec_flag = 1;
    CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);  /* 清除挂起中断 */
//        SEI();//打开总中断
}



u8 CAN2_Send_Msg(u8* msg,u8 len,u16 ID)
{
    u8 mbox;
    u16 i=0;
    CanTxMsg TxMessage;
    TxMessage.StdId=ID;         // 标准标识符11位
    TxMessage.ExtId=ID;         // 设置扩展标示符(29位)
    TxMessage.IDE=CAN_ID_STD;                  // 1使用扩展标识符,0使用标准标识符
    TxMessage.RTR=CAN_RTR_DATA;                  // 消息类型为数据帧,一帧8位
    TxMessage.DLC=len;                                                         // 发送两帧信息
    for(i=0; i<len; i++)
        TxMessage.Data[i]=msg[i];                                 // 第一帧信息
    mbox= CAN_Transmit(CAN2, &TxMessage);
    i=0;
    while((CAN_TransmitStatus(CAN2, mbox)==CANTXFAILED)&&(i<0XFFF))i++;        //等待发送结束
    if(i>=0XFFF)return 1;
    return 0;

}
//CAN2中断程序
void CAN2_RX0_IRQHandler(void)
{

    CanRxMsg RxMessage;
    unsigned char i;
    can2_rec_flag = 1;

    CAN_Receive(CAN2,CAN_FIFO0, &RxMessage);  /* 此函数包含释放提出报文了的,在非必要时,不需要自己释放 */
    for(i = 0; i < 8; i ++)
    {
        CAN2_DATA[i] = RxMessage.Data[i];
    }

    CAN_ClearITPendingBit(CAN2,CAN_IT_FMP0);  /* 清除挂起中断 */
//        CAN2_Send_Msg(CAN2_DATA,8,0x0104);
//        SEI();//打开总中断
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

473

主题

7517

帖子

30

粉丝