/********************************************************************************************************* * * File : main.c * Hardware Environment: * Build Environment : RealView MDK-ARM Version: 4.20 * Version : V1.0 * By : * * (c) Copyright 2005-2011, WaveShare * http://www.waveshare.net * All Rights Reserved * *********************************************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include "stm32f10x.h" #include <stdio.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__ */ /* Private variables ---------------------------------------------------------*/ __IO uint32_t Result = 0; /* for return of the interrupt handling */ /* Private function prototypes -----------------------------------------------*/ void GPIO_Configuration(void); void USART_Configuration(void); void NVIC_Configuration(void); int CAN_Polling(void); int CAN_Interrupt(void); /******************************************************************************* * Function Name : Delay * Description : Delay Time * Input : - nCount: Delay Time * Output : None * Return : None * Attention : None *******************************************************************************/ void Delay (uint32_t nCount) { for(; nCount != 0; nCount--); } /******************************************************************************* * Function Name : main * Description : Main program * Input : None * Output : None * Return : None * Attention : None *******************************************************************************/ int main(void) { int TestRx; NVIC_Configuration(); GPIO_Configuration(); USART_Configuration(); printf(" **************************************************************** "); printf("CAN-Bus Test "); /* CAN transmit at 100Kb/s and receive by polling in loopback mode */ TestRx = CAN_Polling(); if (TestRx == DISABLE) { printf("CAN-Bus by polling in loopback mode is False "); } else { printf("CAN-Bus by polling in loopback mode is OK "); } /* CAN transmit at 500Kb/s and receive by interrupt in loopback mode */ TestRx = CAN_Interrupt(); if (TestRx == DISABLE) { printf("CAN-Bus by interrupt in loopback mode is False "); } else { printf("CAN-Bus by interrupt in loopback mode is OK "); } /* Infinite loop */ while (1) { /*====LED-ON=======*/ GPIO_SetBits(GPIOF , GPIO_Pin_6); GPIO_SetBits(GPIOF , GPIO_Pin_7); GPIO_SetBits(GPIOF , GPIO_Pin_8); GPIO_SetBits(GPIOF , GPIO_Pin_9); Delay(0xfffff); Delay(0xfffff); Delay(0x5ffff); /*====LED-OFF=======*/ GPIO_ResetBits(GPIOF , GPIO_Pin_6); GPIO_ResetBits(GPIOF , GPIO_Pin_7); GPIO_ResetBits(GPIOF , GPIO_Pin_8); GPIO_ResetBits(GPIOF , GPIO_Pin_9); Delay(0xfffff); Delay(0xfffff); Delay(0x5ffff); } } /******************************************************************************* * Function Name : GPIO_Configuration * Description : Configures the different GPIO ports. * Input : None * Output : None * Return : None * Attention : None *******************************************************************************/ void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure;//初始化I/O RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOF , ENABLE); //使能高速APB2时钟,使能端口时钟 /* CAN1 Periph clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); //使能低速APB1时钟,使能端口时钟 /* Configure CAN pin: TX */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//PB9端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_PinRemapConfig(AFIO_MAPR_CAN_REMAP_REMAP2 , ENABLE); /** * LED1 -> PF6 , LED2 -> PF7 , LED3 -> PF8 , LED4 -> PF9 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_Init(GPIOF, &GPIO_InitStructure); } /******************************************************************************* * Function Name : NVIC_Configuration * Description : Configures the nested vectored interrupt controller. * Input : None * Output : None * Return : None * Attention : None *******************************************************************************/ void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* Enable CAN1 RX0 interrupt IRQ channel */ NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占式中断优先级为0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//响应式中断优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中断 NVIC_Init(&NVIC_InitStructure); } /******************************************************************************* * Function Name : CAN_Polling * Description : Configures the CAN, transmit and receive by polling. * Input : None * Output : None * Return : PASSED if the reception is well done, FAILED in other case * Attention : None *******************************************************************************/ int CAN_Polling(void) { CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; CanTxMsg TxMessage;//定义发送消息 CanRxMsg RxMessage;//描述接受消息 uint32_t i = 0;//1个字节 uint8_t TransmitMailbox = 0;//4个字节 /* 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;//接受溢出时FIFO不锁定,下一个收到的报文覆盖原有报文 CAN_InitStructure.CAN_TXFP=DISABLE;//优先级由报文的标识符来决定 CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;//CAN硬件工作环回模式 CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;//重新同步跳跃宽度为2个时间单位 CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;//时间段为8个时间单位 CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;//时间段为7个时间单位 CAN_InitStructure.CAN_Prescaler=5;//设定一个时间单位的长度为5,范围(1~1024) CAN_Init(CAN1, &CAN_InitStructure); /* CAN filter init */ CAN_FilterInitStructure.CAN_FilterNumber=0;//设置过滤器组0,范围为0~13 CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//设定过滤器组为屏蔽位模式 CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//过滤器位宽为32位过滤器一个 CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;//设定过滤器标识符高位(32为高位段,16位为第一个) CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;//设定过滤器标识符低位(32为低位段,16位为第二个) CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//设定过滤器标识符高位(32为高位段,16位为第一个) CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;//设定过滤器标识符低位(32为低位段,16位为第二个) CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0; CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;/使能过滤器 CAN_FilterInit(&CAN_FilterInitStructure); /* transmit */ TxMessage.StdId=0x11;// 标准标识符 TxMessage.RTR=CAN_RTR_DATA;// 数据帧 TxMessage.IDE=CAN_ID_STD;// 标准帧 TxMessage.DLC=2;// 要发送的数据长度 TxMessage.Data[0]=0xCA; TxMessage.Data[1]=0xFE; TransmitMailbox=CAN_Transmit(CAN1, &TxMessage);//启动传输一个消息 i = 0; while((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK) && (i != 0xFF))//判断 信息有没有发送成功的 { i++; } i = 0; while((CAN_MessagePending(CAN1, CAN_FIFO0) < 1) && (i != 0xFF))//判断 接收邮箱有没有收到信息 { i++; } /* receive */ RxMessage.StdId=0x00; RxMessage.IDE=CAN_ID_STD; RxMessage.DLC=0; RxMessage.Data[0]=0x00; RxMessage.Data[1]=0x00; CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//接受一个消息 if (RxMessage.StdId!=0x11) { return DISABLE; } if (RxMessage.IDE!=CAN_ID_STD) { return DISABLE; } if (RxMessage.DLC!=2) { return DISABLE; } if ((RxMessage.Data[0]<<8|RxMessage.Data[1])!=0xCAFE) { return DISABLE; } return ENABLE; /* Test Passed */ } /******************************************************************************* * Function Name : NVIC_Configuration * Description : Configures the CAN, transmit and receive using interrupt. * Input : None * Output : None * Return : PASSED if the reception is well done, FAILED in other case * Attention : None *******************************************************************************/ int CAN_Interrupt(void) { CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; CanTxMsg TxMessage; uint32_t i = 0; /* 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_LoopBack; CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; CAN_InitStructure.CAN_BS1=CAN_BS1_8tq; CAN_InitStructure.CAN_BS2=CAN_BS2_7tq; CAN_InitStructure.CAN_Prescaler=1; CAN_Init(CAN1, &CAN_InitStructure); /* CAN filter init */ CAN_FilterInitStructure.CAN_FilterNumber=1; 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=CAN_FIFO0;//此过滤器组关联到接收FIFO0 CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; CAN_FilterInit(&CAN_FilterInitStructure); /* CAN FIFO0 message pending interrupt enable */ CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);//CAN中断开通设置中断源的动作条件 /* transmit 1 message */ TxMessage.StdId=0x00; TxMessage.ExtId=0x1234;//扩展标识符 TxMessage.IDE=CAN_ID_EXT; TxMessage.RTR=CAN_RTR_DATA; TxMessage.DLC=2; TxMessage.Data[0]=0xDE; TxMessage.Data[1]=0xCA; CAN_Transmit(CAN1, &TxMessage); /* initialize the value that will be returned */ Result = 0xFF; /* receive message with interrupt handling */ i=0; while((Result == 0xFF) && (i < 0xFFF)) { i++; } if (i == 0xFFF) { Result=0; } /* disable interrupt handling */ CAN_ITConfig(CAN1, CAN_IT_FMP0, DISABLE); return (FunctionalState)Result; } #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 ", file, line) */ /* Infinite loop */ while (1) { } } #endif /********************************************************************************************************* END FILE *********************************************************************************************************/