Giỏ hàng
Danh mục sản phẩm

Lập trình can bus STM32

Đăng bởi Buiprohd@gmail.com ngày bình luận

Các bạn đã bao giờ tự hỏi tại sao ô tô lại dùng mạng can bus 

Vì ưu điểm can bus tiết kiệm dây và truyền đi xa

Chi phí thấp so với các giao tiếp khác

Phần cứng can bus STM32 

ở đây mình dùng cách ly iso và dùng TVS để bảo vệ đường truyền

Về code:

ở hàm main.c

#include “stm32f4xx.h”
#include “usart.h”
#include <stdlib.h>

#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to ‘Yes’) calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
#define USER_KEY_Port GPIOF
#define USER_KEY_Pin GPIO_Pin_10
#define USER_KEY_RCC_AHBPeriph RCC_AHB1Periph_GPIOF

/* Private macro ————————————————————-*/
/* Private variables ———————————————————*/
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CanTxMsg TxMessage;
uint8_t KeyNumber = 0x0;

/* Private variables ———————————————————*/
uint16_t CAN1_ID;
uint8_t CAN1_DATA0,CAN1_DATA1,CAN1_DATA2,CAN1_DATA3,CAN1_DATA4,CAN1_DATA5,CAN1_DATA6,CAN1_DATA7;

uint16_t CAN2_ID;
uint8_t CAN2_DATA0,CAN2_DATA1,CAN2_DATA2,CAN2_DATA3,CAN2_DATA4,CAN2_DATA5,CAN2_DATA6,CAN2_DATA7;

__IO uint8_t Can1Flag,Can2Flag;

void CAN1_Config(void);
void CAN2_Config(void);
void NVIC_Config(void);
void Can1WriteData(uint16_t ID);
void Can2WriteData(uint16_t ID);
void Key_Config(void);
void Delay1(__IO uint32_t num)
{
__IO uint32_t index = 0;

/* default system clock is 72MHz */
for(index = (1680000 * num); index != 0; index–)
{
}
}
/* Private functions ———————————————————*/

/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
uint8_t error_can=0;
USART_Configuration();
printf(“\r\nCAN-Bus Test \r\n”);
printf(“CAN-Bus Speed 100kHz \r\n”);
printf(“Please click USER key.\r\n”);

Key_Config();
CAN1_Config();
CAN2_Config();
NVIC_Config();
/* Infinite loop */
while (1)
{
// while(GPIO_ReadInputDataBit(USER_KEY_Port,USER_KEY_Pin));
// Can2WriteData(0x123);
// printf(“\r\nCAN-Bus Test \r\n”);
// printf(“CAN-Bus Speed 100kHz \r\n”);
// printf(“Please click USER key.\r\n”);
// printf(“\r\nCAN-Bus Test \r\n”);
// TxMessage.Data[0] = 0x12;
// CAN_Transmit(CAN2, &TxMessage);
//Delay1(5);
// TxMessage.Data[0] = 0x02;
// CAN_Transmit(CAN2, &TxMessage);

if( Can2Flag == ENABLE )
{
Can2Flag = DISABLE;

printf(“CAN2 Receive Data \r\n”);

// printf(“CAN Receive Data \r\n”);
//printf(“CAN ID %x \r\n”,CAN_ID);
//printf(“CAN ID %x \r\n”, data_len );
// printf(“CAN_DATA0 %x%x%x%x%x%x%x%x \r\n”,CAN_DATA0,CAN_DATA1,CAN_DATA2,CAN_DATA3,CAN_DATA4,CAN_DATA5,CAN_DATA6,CAN_DATA7);

}

if( Can1Flag == ENABLE )
{
Can1Flag = DISABLE;

printf(“CAN2 Receive Data \r\n”);

// printf(“CAN Receive Data \r\n”);
printf(“CAN ID %x \r\n”,CAN1_ID);
printf(“CAN ID %x \r\n”, CAN1_DATA0);
// printf(“CAN_DATA0 %x%x%x%x%x%x%x%x \r\n”,CAN_DATA0,CAN_DATA1,CAN_DATA2,CAN_DATA3,CAN_DATA4,CAN_DATA5,CAN_DATA6,CAN_DATA7);

}

// Delay1(1);
}
}

void Key_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(USER_KEY_RCC_AHBPeriph, ENABLE);

/* Configure Input pushpull mode */
GPIO_InitStructure.GPIO_Pin = USER_KEY_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(USER_KEY_Port, &GPIO_InitStructure);
}

/**
* @brief Configures the CAN.
* @param None
* @retval None
*/
void CAN1_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

/* CAN GPIOs configuration **************************************************/

/* Enable GPIO clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH | RCC_AHB1Periph_GPIOI, ENABLE);

/* Connect CAN pins */
GPIO_PinAFConfig(GPIOH, GPIO_PinSource13, GPIO_AF_CAN1);
GPIO_PinAFConfig(GPIOI, GPIO_PinSource9, GPIO_AF_CAN1);

/* Configure CAN RX and TX pins */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOH, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOI, &GPIO_InitStructure);

/* CAN configuration ********************************************************/
/* Enable CAN clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

/* CAN register init */
CAN_DeInit(CAN1);
CAN_StructInit(&CAN_InitStructure);

/* CAN cell init */
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 = DISABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;

// CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;//
// CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq;//
// CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq;//
// CAN_InitStructure.CAN_Prescaler = 45;//
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;//

/* CAN Baudrate = 1MBps (CAN clocked at 30 MHz) */
CAN_InitStructure.CAN_BS1 = CAN_BS1_2tq;//
CAN_InitStructure.CAN_BS2 = CAN_BS2_1tq;//
CAN_InitStructure.CAN_Prescaler = 42;//

CAN_Init(CAN1, &CAN_InitStructure);

/* CAN filter init */
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);

/* Transmit Structure preparation */
TxMessage.StdId = 0x321;
TxMessage.ExtId = 0x01;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 1;

/* Enable FIFO 0 message pending Interrupt */
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
}

void CAN2_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

/* CAN GPIOs configuration **************************************************/

/* Enable GPIO clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

/* Connect CAN pins to AF9 */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_CAN2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_CAN2);

/* Configure CAN RX and TX pins */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);

/* CAN configuration ********************************************************/
/* Enable CAN clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);

/* CAN register init */
CAN_DeInit(CAN2);
CAN_StructInit(&CAN_InitStructure);

/* CAN cell init */
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 = DISABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;

//84M/((1+6+8)*2)=
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;//
CAN_InitStructure.CAN_BS1 = CAN_BS1_2tq;//
CAN_InitStructure.CAN_BS2 = CAN_BS2_1tq;//
CAN_InitStructure.CAN_Prescaler = 42;//

CAN_Init(CAN2, &CAN_InitStructure);

CAN_FilterInitStructure.CAN_FilterNumber = 14;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);

/* Transmit Structure preparation */
TxMessage.StdId = 0x321;
TxMessage.ExtId = 0x01;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 1;

/* Enable FIFO 0 message pending Interrupt */
CAN_ITConfig(CAN2, CAN_IT_FMP0, ENABLE);
}
/**
* @brief Configures the NVIC for CAN.
* @param None
* @retval None
*/
void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/*******************************************************************************
* Function Name : Can1WriteData
* Description : Can1 Write Date to CAN-BUS
* Input : None
* Output : None
* Return : None
* Attention : None
*******************************************************************************/
void Can1WriteData(uint16_t ID)
{
CanTxMsg TxMessage;

CAN1_DATA0=rand()%0xff; CAN1_DATA1=rand()%0xff;
CAN1_DATA2=rand()%0xff; CAN1_DATA3=rand()%0xff;
CAN1_DATA4=rand()%0xff; CAN1_DATA5=rand()%0xff;
CAN1_DATA6=rand()%0xff; CAN1_DATA7=rand()%0xff;

/* transmit */
TxMessage.StdId = ID;
//TxMessage.ExtId = 0x00;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 8;
TxMessage.Data[0] = CAN1_DATA0;
TxMessage.Data[1] = CAN1_DATA1;
TxMessage.Data[2] = CAN1_DATA2;
TxMessage.Data[3] = CAN1_DATA3;
TxMessage.Data[4] = CAN1_DATA4;
TxMessage.Data[5] = CAN1_DATA5;
TxMessage.Data[6] = CAN1_DATA6;
TxMessage.Data[7] = CAN1_DATA7;
CAN_Transmit(CAN1,&TxMessage);
}

/*******************************************************************************
* Function Name : CanWriteData
* Description : Can Write Date to CAN-BUS
* Input : None
* Output : None
* Return : None
* Attention : None
*******************************************************************************/
void Can2WriteData(uint16_t ID)
{
CanTxMsg TxMessage;

CAN2_DATA0=rand()%0xff; CAN2_DATA1=rand()%0xff;
CAN2_DATA2=rand()%0xff; CAN2_DATA3=rand()%0xff;
CAN2_DATA4=rand()%0xff; CAN2_DATA5=rand()%0xff;
CAN2_DATA6=rand()%0xff; CAN2_DATA7=rand()%0xff;

/* transmit */
TxMessage.StdId = ID;
//TxMessage.ExtId = 0x00;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 8;
TxMessage.Data[0] = CAN2_DATA0;
TxMessage.Data[1] = CAN2_DATA1;
TxMessage.Data[2] = CAN2_DATA2;
TxMessage.Data[3] = CAN2_DATA3;
TxMessage.Data[4] = CAN2_DATA4;
TxMessage.Data[5] = CAN2_DATA5;
TxMessage.Data[6] = CAN2_DATA6;
TxMessage.Data[7] = CAN2_DATA7;
CAN_Transmit(CAN2,&TxMessage);
}
#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 2011 STMicroelectronics *****END OF FILE****/

ở hàm IT.C

/**
******************************************************************************
* @file I2C/EEPROM/stm32f4xx_it.c
* @author MCD Application Team
* @version V1.0.0
* @date 30-September-2011
* @brief Main Interrupt Service Routines.
* This file provides template for all exceptions handler and
* peripherals interrupt service routine.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/

/* Includes ——————————————————————*/
#include “stm32f4xx_it.h”
#include “usart.h”

#define USARTx_IRQHANDLER USART1_IRQHandler

extern uint16_t CAN1_ID;
extern uint8_t CAN1_DATA0,CAN1_DATA1,CAN1_DATA2,CAN1_DATA3,CAN1_DATA4,CAN1_DATA5,CAN1_DATA6,CAN1_DATA7;

extern uint16_t CAN2_ID;
extern uint8_t CAN2_DATA0,CAN2_DATA1,CAN2_DATA2,CAN2_DATA3,CAN2_DATA4,CAN2_DATA5,CAN2_DATA6,CAN2_DATA7;

extern __IO uint8_t Can1Flag,Can2Flag;
/** @addtogroup STM32F2xx_StdPeriph_Examples
* @{
*/

/** @addtogroup IOToggle
* @{
*/

/* Private typedef ———————————————————–*/
/* Private define ————————————————————*/
/* Private macro ————————————————————-*/
/* Private variables ———————————————————*/
/* Private function prototypes ———————————————–*/
/* Private functions ———————————————————*/

/******************************************************************************/
/* Cortex-M4 Processor Exceptions Handlers */
/******************************************************************************/

/**
* @brief This function handles NMI exception.
* @param None
* @retval None
*/
void NMI_Handler(void)
{
}

/**
* @brief This function handles Hard Fault exception.
* @param None
* @retval None
*/
void HardFault_Handler(void)
{
/* Go to infinite loop when Hard Fault exception occurs */
while (1)
{
}
}

/**
* @brief This function handles Memory Manage exception.
* @param None
* @retval None
*/
void MemManage_Handler(void)
{
/* Go to infinite loop when Memory Manage exception occurs */
while (1)
{
}
}

/**
* @brief This function handles Bus Fault exception.
* @param None
* @retval None
*/
void BusFault_Handler(void)
{
/* Go to infinite loop when Bus Fault exception occurs */
while (1)
{
}
}

/**
* @brief This function handles Usage Fault exception.
* @param None
* @retval None
*/
void UsageFault_Handler(void)
{
/* Go to infinite loop when Usage Fault exception occurs */
while (1)
{
}
}

/**
* @brief This function handles SVCall exception.
* @param None
* @retval None
*/
void SVC_Handler(void)
{
}

/**
* @brief This function handles Debug Monitor exception.
* @param None
* @retval None
*/
void DebugMon_Handler(void)
{
}

/**
* @brief This function handles PendSVC exception.
* @param None
* @retval None
*/
void PendSV_Handler(void)
{
}

/**
* @brief This function handles SysTick Handler.
* @param None
* @retval None
*/
void SysTick_Handler(void)
{
}

/******************************************************************************/
/* STM32F2xx Peripherals Interrupt Handlers */
/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */
/* available peripheral interrupt handler’s name please refer to the startup */
/* file (startup_stm32f2xx.s). */
/******************************************************************************/
void USARTx_IRQHANDLER(void)
{

}
/**
* @brief This function handles CAN1 RX0 request.
* @param None
* @retval None
*/
void CAN1_RX0_IRQHandler(void)
{
CanRxMsg RxMessage;
CAN_Receive(CAN1,CAN_FIFO0, &RxMessage);
CAN1_ID=RxMessage.StdId;
CAN1_DATA0=RxMessage.Data[0];
CAN1_DATA1=RxMessage.Data[1];
CAN1_DATA2=RxMessage.Data[2];
CAN1_DATA3=RxMessage.Data[3];
CAN1_DATA4=RxMessage.Data[4];
CAN1_DATA5=RxMessage.Data[5];
CAN1_DATA6=RxMessage.Data[6];
CAN1_DATA7=RxMessage.Data[7];
CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);
Can1Flag = ENABLE;
}

/**
* @brief This function handles CAN1 RX0 request.
* @param None
* @retval None
*/
void CAN2_RX0_IRQHandler(void)
{
CanRxMsg RxMessage;
CAN_Receive(CAN2,CAN_FIFO0, &RxMessage);
CAN2_ID=RxMessage.StdId;
CAN2_DATA0=RxMessage.Data[0];
CAN2_DATA1=RxMessage.Data[1];
CAN2_DATA2=RxMessage.Data[2];
CAN2_DATA3=RxMessage.Data[3];
CAN2_DATA4=RxMessage.Data[4];
CAN2_DATA5=RxMessage.Data[5];
CAN2_DATA6=RxMessage.Data[6];
CAN2_DATA7=RxMessage.Data[7];
CAN_ClearITPendingBit(CAN2,CAN_IT_FMP0);
Can2Flag = ENABLE;
}
/**
* @brief This function handles PPP interrupt request.
* @param None
* @retval None
*/
/*void PPP_IRQHandler(void)
{
}*/

/**
* @}
*/

/**
* @}
*/

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


Cũ hơn Mới hơn