我目前正在与意法半导体的开发板Nucleo-F103RB合作。我打算使用环回模式测试集成在微控制器中的bxCAN,直接从CAN_TX1发送到CAN_RX1而无需CAN收发器。这是我到现在为止编写的代码:
#include <stm32f10x.h>
#define LED_pin 5
/* GPIO CAN: PD0 E PD1 */
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
GPIO_InitTypeDef GPIO_InitStructure, LED_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
uint32_t i;
CanTxMsg TxMessage;
CanRxMsg RxMessage;
uint8_t TransmitMailbox = 0;
void clock_init(void)
{
/*Configure all clocks to max for best performance.
* If there are EMI, power, or noise problems, try slowing the clocks*/
/* First set the flash latency to work with our clock*/
/*000 Zero wait state, if 0 MHz < SYSCLK <= 24 MHz
001 One wait state, if 24 MHz < SYSCLK <= 48 MHz
010 Two wait states, if 48 MHz < SYSCLK <= 72 MHz */
FLASH_SetLatency(FLASH_Latency_1);
/* Start with HSI clock (internal 8mhz), divide by 2 and multiply by 9 to
* get maximum allowed frequency: 36Mhz
* Enable PLL, wait till it's stable, then select it as system clock*/
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9);
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Set HCLK, PCLK1, and PCLK2 to SCLK (these are default */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1);
/* Set ADC clk to 9MHz (14MHz max, 18MHz default)*/
RCC_ADCCLKConfig(RCC_PCLK2_Div4);
/*To save power, use below functions to stop the clock to ceratin
* peripherals
* RCC_PeriphClockCmd
*/
}
void LED_init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
LED_InitStructure.GPIO_Pin = GPIO_Pin_5;
LED_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
LED_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &LED_InitStructure);
}
void CAN_TX()
{
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) != CAN_TxStatus_Ok) && (i != 0xFFFF))
{
i++;
}
i = 0;
while((CAN_MessagePending(CAN1, CAN_FIFO0) < 1) && (i != 0xFFFF))
{
i++;
}
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);
}
void CAN_init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
/* Configure CAN pins: CAN_TX and CAN_RX */
/* CAN 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);
/* CAN 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);
GPIO_PinRemapConfig(GPIO_Remap1_CAN1,ENABLE);
// /* Enable CAN reset state */
// RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1, ENABLE);
// /* Release CAN from reset state */
// RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1, DISABLE);
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;;
NVIC_Init(&NVIC_InitStructure);
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 = ENABLE;
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_12tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq;
CAN_InitStructure.CAN_Prescaler = 1;
// 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=DISABLE;
CAN_Init(CAN1, &CAN_InitStructure);
// CAN_FilterInit(&CAN_FilterInitStructure);
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
}
void main (void)
{
clock_init();
LED_init();
CAN_init();
CAN_TX();
while(1);
}
void USB_LP_CAN1_RX0_IRQHandler(void)
{
if(CAN_GetITStatus(CAN1, CAN_IT_FMP0) != RESET)
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);
}
void assert_failed(u8* file, u32 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)
{
for(i=0;i<100000;i++);
}
}
我正在使用IAR作为IDE。问题是:我能够(至少似乎)发送我的信息;但是当检查CAN的FIFO中是否有任何未决消息时它会停止:
while((CAN_MessagePending(CAN1, CAN_FIFO0) < 1) && (i != 0xFFFF))
我还查看了用户手册中列出的有关CAN使用情况的寄存器的位值。有人看到了bug的位置吗?提前谢谢。