我采用MXCHIP的MCBSTM32板子2块,用DB9直通线连接2块板子上的CAN接口,用万用表测量2,7脚连通。我写了一个发送测试程序和一个接收测试程序如下,程序在CAN_Mode_LoopBack能自发自收,但是改成CAN_Mode_Normal收发不正常。各位大侠看看问题在哪里?
发送程序:
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"
/* Local includes ------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
vu32 ret; /* for return of the interrupt handling */
volatile TestStatus TestRx;
ErrorStatus HSEStartUpStatus;
/* Private functions ---------------------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
TestStatus CAN_Polling(void);
TestStatus CAN_Interrupt(void);
/*******************************************************************************
* Function Name : main
* Description : Main program
* Input : None
* Output : None
* Return : None
*******************************************************************************/
int main(void)
{
#ifdef DEBUG
debug();
#endif
RCC_Configuration(); // System Clocks Configuration
NVIC_Configuration(); // NVIC Configuration
GPIO_Configuration(); // GPIO ports pins Configuration
TestRx = CAN_Polling(); // CAN transmit at 100Kb/s and receive by polling in loopback mode
if (TestRx == FAILED) {
GPIO_SetBits(GPIOB, GPIO_Pin_10); // Turn on led connected to PC.08 pin (LD3)
}
else {
GPIO_SetBits(GPIOB, GPIO_Pin_11); // Turn on led connected to PC.06 pin (LD1)
}
while (1) { }
}
/*******************************************************************************
* Function Name : RCC_Configuration
* Description : Configures the different system clocks.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void RCC_Configuration(void)
{
RCC_DeInit(); /* RCC system reset(for debug purpose) */
RCC_HSEConfig(RCC_HSE_ON); /* Enable HSE */
HSEStartUpStatus = RCC_WaitForHSEStartUp(); /* Wait till HSE is ready */
if(HSEStartUpStatus == SUCCESS) {
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /* Enable Prefetch Buffer */
RCC_HCLKConfig(RCC_SYSCLK_Div1); /* HCLK = SYSCLK */
RCC_PCLK2Config(RCC_HCLK_Div1); /* PCLK2 = HCLK */
RCC_PCLK1Config(RCC_HCLK_Div2); /* PCLK1 = HCLK/2 */
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE); /* Select HSE as system clock source */
while(RCC_GetSYSCLKSource() != 0x04) { // Wait till HSE is used as system clock source
}
}
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); /* GPIOA and GPIOC clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE); /* CAN Periph clock enable */
}
/*******************************************************************************
* Function Name : GPIO_Configuration
* Description : Configures the different GPIO ports.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); /* Configure PC.06, PC.07, PC.08 and PC.09 as Output push-pull */
/* Configure CAN pin: RX */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
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_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Enable the USART2 Pins Software Remapping */
GPIO_PinRemapConfig(GPIO_Remap1_CAN, ENABLE);
}
/*******************************************************************************
* Function Name : NVIC_Configuration
* Description : Configures the NVIC and Vector Table base address.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); /* Set the Vector Table base location at 0x20000000 */
#else /* VECT_TAB_FLASH */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); /* Set the Vector Table base location at 0x08000000 */
#endif
/* enabling interrupt */
NVIC_InitStructure.NVIC_IRQChannel=USB_LP_CAN_RX0_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/*******************************************************************************
* Function Name : CAN_Polling
* Description : Configures the CAN and transmit and receive by polling
* Input : None
* Output : None
* Return : PASSED if the reception is well done, FAILED in other case
*******************************************************************************/
TestStatus CAN_Polling(void)
{
u8 Error;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CanTxMsg TxMessage;
u32 i = 0;
u8 TransmitMailbox;
/* CAN register init */
CAN_DeInit();
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_Mode_Normal; // 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 = 5;
Error = CAN_Init(&CAN_InitStructure);
if (Error == 0)
return FAILED;
/* 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 = CAN_FIFO0; //0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
/* transmit */
TxMessage.StdId = 0x18;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 8;
TxMessage.Data[0] = 0x40;
TxMessage.Data[1] = 0x40;
TxMessage.Data[2] = 0x45;
TxMessage.Data[3] = 0x51;
TxMessage.Data[4] = 0x52;
TxMessage.Data[5] = 0x65;
TxMessage.Data[6] = 0x61;
TxMessage.Data[7] = 0x64; // @@EQRead
TransmitMailbox = CAN_Transmit(&TxMessage);
i = 0;
while((CAN_TransmitStatus(TransmitMailbox) != CANTXOK) && (i != 0xFF)) {
i++;
}
if (i < 80) return PASSED; // Test Passed
else return FAILED;
}
接收程序:
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"
/* Local includes ------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
vu32 ret; /* for return of the interrupt handling */
volatile TestStatus TestRx;
ErrorStatus HSEStartUpStatus;
/* Private functions ---------------------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
TestStatus CAN_Polling(void);
TestStatus CAN_Interrupt(void);
/*******************************************************************************
* Function Name : main
* Description : Main program
* Input : None
* Output : None
* Return : None
*******************************************************************************/
/*******************************************************************************
* Function Name : RCC_Configuration
* Description : Configures the different system clocks.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void RCC_Configuration(void)
{
RCC_DeInit(); /* RCC system reset(for debug purpose) */
RCC_HSEConfig(RCC_HSE_ON); /* Enable HSE */
HSEStartUpStatus = RCC_WaitForHSEStartUp(); /* Wait till HSE is ready */
if(HSEStartUpStatus == SUCCESS) {
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /* Enable Prefetch Buffer */
RCC_HCLKConfig(RCC_SYSCLK_Div1); /* HCLK = SYSCLK */
RCC_PCLK2Config(RCC_HCLK_Div1); /* PCLK2 = HCLK */
RCC_PCLK1Config(RCC_HCLK_Div2); /* PCLK1 = HCLK/2 */
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE); /* Select HSE as system clock source */
while(RCC_GetSYSCLKSource() != 0x04) { // Wait till HSE is used as system clock source
}
}
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); /* GPIOA and GPIOC clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE); /* CAN Periph clock enable */
}
/*******************************************************************************
* Function Name : GPIO_Configuration
* Description : Configures the different GPIO ports.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); /* Configure PC.06, PC.07, PC.08 and PC.09 as Output push-pull */
/* Enable the USART2 Pins Software Remapping */
GPIO_PinRemapConfig(GPIO_Remap1_CAN, ENABLE);
/* Configure CAN pin: RX */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
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_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/*******************************************************************************
* Function Name : NVIC_Configuration
* Description : Configures the NVIC and Vector Table base address.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); /* Set the Vector Table base location at 0x20000000 */
#else /* VECT_TAB_FLASH */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); /* Set the Vector Table base location at 0x08000000 */
#endif
/* enabling interrupt */
NVIC_InitStructure.NVIC_IRQChannel=USB_LP_CAN_RX0_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/*******************************************************************************
* Function Name : CAN_Configuration
* Description : Configures the CAN
* Input : None
* Output : None
* Return : PASSED if the configration is well done, FAILED in other case
*******************************************************************************/
TestStatus CAN_Configuration(void)
{
u8 Error;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
/* CanTxMsg TxMessage;
u32 i = 0;
u8 TransmitMailbox; */
CAN_DeInit(); // CAN register init
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 = DISABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;//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 = 5;
Error = CAN_Init(&CAN_InitStructure); // CAN cell init
if (Error == 0)
return FAILED;
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0300; // StdId << 20 | ExID << 2 | IDE << 1 | RTR
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000; // StdId << 20 | ExID << 2 | IDE << 1 | RTR
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure); // CAN filter init
/* transmit
TxMessage.StdId = 0x18;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 8;
TxMessage.Data[0] = 0x40;
TxMessage.Data[1] = 0x40;
TxMessage.Data[2] = 0x45;
TxMessage.Data[3] = 0x51;
TxMessage.Data[4] = 0x52;
TxMessage.Data[5] = 0x65;
TxMessage.Data[6] = 0x61;
TxMessage.Data[7] = 0x64; // @@EQRead
TransmitMailbox = CAN_Transmit(&TxMessage); */
return PASSED;
}
/*******************************************************************************
* Function Name : main
* Description : Main program
* Input : None
* Output : None
* Return : None
*******************************************************************************/
int main(void)
{
CanRxMsg RxMessage;
u32 i = 0;
#ifdef DEBUG
debug();
#endif
RCC_Configuration(); // System Clocks Configuration
NVIC_Configuration(); // NVIC Configuration
GPIO_Configuration(); // GPIO ports pins Configuration
do {
TestRx = CAN_Configuration(); // CAN transmit at 100Kb/s and receive by polling in loopback mode
} while (TestRx == 0);
/* receive */
RxMessage.StdId = 0x00;
RxMessage.IDE = CAN_ID_STD;
RxMessage.DLC = 0;
for (i = 0; i < 8; i++) {
RxMessage.Data = 0x00;
}
while (1) {
if (CAN_MessagePending(CAN_FIFO0)) {
CAN_Receive(CAN_FIFO0, &RxMessage);
TestRx = PASSED;
if (RxMessage.StdId!=0x18)
TestRx = FAILED;
/* if (RxMessage.IDE!=CAN_ID_STD)
TestRx = FAILED;
if (RxMessage.DLC!=2)
TestRx = FAILED;
if ((RxMessage.Data[0] << 8 | RxMessage.Data[1]) != 0xCAFE)
TestRx = FAILED; */
if (TestRx == FAILED) {
GPIO_SetBits(GPIOB, GPIO_Pin_12); // Turn on led connected to PC.08 pin (LD3)
}
else {
GPIO_SetBits(GPIOB, GPIO_Pin_13); // Turn on led connected to PC.06 pin (LD1)
}
}
}
}
我就是根据你在论坛上的例程改的,
我看了好多遍一直没发现问题,但就是通信不上
我的例程无需修改
应该可以在你的板子上运行。
“用万用表测量2,7脚连通”不明白是指什么?
“用万用表测量2,7脚连通”(应该是分别连通)代表硬件连
因为在MCBSTM32的板子上CANH和CANL连接到DB9的2脚和7脚
在MCBSTM32的板子上CANTX和CANRX是从DB8和DB9引出的所以引脚需要映射一下。
另外,在接收程序校验ID好像和发送ID不一致。我参照的是“https://bbs.eeworld.com.cn/club/bbs/list.asp?boardid=49&t=3051536&tp=stm32%u7684can%26nbsp%3B%26nbsp%3B%u95EE%u9898%u592A%u591A%u4E86”帖子。
MCBSTM32的板子有问题
去年年初时使用那块板子调试过,它的CAN的两个引脚上连了其他的元器件,具体记不得了,你去Keil的网站上看,那里有解决方案。
MCBSTM32板子的can引脚DB8/DB9还通过74LV244连接LED
这个我想对CAN通信应该没有影响吧?在KEIL网站上找到一段相关的信息:主要针对MCBSTM32 PCB1.0版,可能是在DB8和DB9之间有一个R38造成短路,他们建议将此电阻开路。我用的是1.1版的PCB,在板子上也没有R38这个电阻,我想是不是新的PCB对此做了改进。