上周就已经把CAN通讯调通了,不管是查询模式还是中断模式都跑的很好,这周给板子加了个UCOS,2.86版本的。然后把CAN通讯加上去,CAN数据死活发不出来。用lookback模式自测,发现可以收到自己发出去的数据,但是用示波器测试发送脚,就是没见到波形,晚上突然有一次看到了波形,对着波形看数据,确实是我发出去的数据,害我纳闷半天,我什么都没改,怎么就好了,断电重启,又不行了,唯一好了一次,我晕。
刚开始怀疑硬件问题,用原来的裸奔程序,CAN通讯就是OK的,硬件应该不会有问题了,问题应该就是出在我移植的UCOS上面,其实也不是移植,官方有现成的,我直接把UCOS那个文件夹就是核心的那块与处理器无关的加了进来,还有ports文件夹加了进来,改了2个中断向量,一个systick的,一个pendsv的,架构和我以前的裸奔程序是一样,在UCOS创建了几个任务,如点灯,LCD,按键,串口发送,接收(串口都是用的中断模式)都没有任何问题,就是CAN通讯死活不行,在发送脚上用示波器测,半点数据都没有,看版主或者其他兄弟有没有碰到过这种情况。
简单点说,就是用lookback模式,程序里面自己可以接收到自己发的数据,但是tx脚就是不出数据(搞的我都以为我用的是静默方式了),各位兄弟碰到过没?
贴下代码,有用过的兄弟帮忙看下
#define GPIO_CAN GPIOB
#define RCC_APB2Periph_GPIO_CAN RCC_APB2Periph_GPIOB
#define GPIO_Pin_RX GPIO_Pin_8
#define GPIO_Pin_TX GPIO_Pin_9
#define GPIO_Remap_CAN GPIO_Remap1_CAN1
void CAN_init(void)
{
// NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// 首先打开电源及时钟
/* GPIO for CAN and GPIO for LEDs clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO |RCC_APB2Periph_GPIO_CAN, ENABLE);
/* CAN1 Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
/* Enable CAN1 RX0 interrupt IRQ channel */
// NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
// 然后配置pin
/* Configure CAN pin: RX */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_RX;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIO_CAN, &GPIO_InitStructure);
/* Configure CAN pin: TX */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_TX;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIO_CAN, &GPIO_InitStructure);
// 映射下
GPIO_PinRemapConfig(GPIO_Remap_CAN , ENABLE);
// 查询方式初始化
CAN_Polling_init();
}
然后是设置速率和过滤器
/**
* @brief Configures the CAN, transmit and receive by polling
* @param None
* @retval : PASSED if the reception is well done, FAILED in other case
*/
void CAN_Polling_init(void)
{
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
/* CAN register init */
CAN_DeInit(CAN1);
// CAN_StructInit(&CAN_InitStructure);
/* CAN cell init */ // 36M 250k速率
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_12tq;
CAN_InitStructure.CAN_BS2=CAN_BS2_3tq;
CAN_InitStructure.CAN_Prescaler=9;
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);
}
然后是查询发送的方式
TestStatus CAN_Polling(void)
{
CanTxMsg TxMessage;
CanRxMsg RxMessage;
uint32_t i = 0;
uint8_t TransmitMailbox = 0;
/* transmit */
TxMessage.StdId=0x6f1;
TxMessage.RTR=CAN_RTR_DATA;
TxMessage.IDE=CAN_ID_STD;
TxMessage.DLC=4;
TxMessage.Data[0]=0x40;
TxMessage.Data[1]=0x02;
TxMessage.Data[2]=0x1a;
TxMessage.Data[3]=0x80;
TransmitMailbox=CAN_Transmit(CAN1, &TxMessage);
i = 0;
// while((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK) && (i != 0xFF))
while((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK) && (i <= 1000))
{
i++;
}
printf("1i is %d\r\n",i);
i = 0;
while((CAN_MessagePending(CAN1, CAN_FIFO0) < 1) && (i != 0xFF))
{
i++;
}
printf("2i is %d\r\n",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);
// printf("RxMessage.StdId is 0x%x,RxMessage.DLC is 0x%x,RxMessage.Data[0] is 0x%x,RxMessage.Data[1] is 0x%x\r\n",
// RxMessage.StdId,RxMessage.DLC,RxMessage.Data[0],RxMessage.Data[1]);
if (RxMessage.StdId!=0x6f1)
{
return FAILED;
}
if (RxMessage.IDE!=CAN_ID_STD)
{
return FAILED;
}
if (RxMessage.DLC!=4)
{
return FAILED;
}
if ((RxMessage.Data[0]<<8|RxMessage.Data[1])!=0x4002)
{
return FAILED;
}
return PASSED; /* Test Passed */
}
这段测试程序放到裸奔程序没有任何问题。
采用lookback方式打印出来接收到的数据也没有问题,用示波器测试CAN的发送脚就是没有任何数据,一直为高电平3.3V。
跟UCOS无关。从症状上来看,应该是CAN的发送引脚跟某些其它外设共用了引脚,导致CAN_TX不正常。其它外设不初始化,就可以找到问题了。
问题解决了。的确跟UCOS没有关系,也跟其他引脚没有关系,设置CAN发送脚时,加了个
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
就可以用了,折腾了我2天,天啊。
裸机跑的时候不加也没有问题,奇怪。我用的是3.0的版本,最新的版本好像已经加了这句。
看样子得用最新的库了,哪位兄弟提供个链接?
CAN_Mode_LoopBack模式时,信号不会发送到TX引脚上,
你将模式改为正常模式
谢谢LS的回答,此问题已经解决,对stm32的CAN的lookback的理解,你可能有些问题,可以去看看STM32关于lookback方式的定义,
哥哥我爱死你了 ,我就是这个问题 一摸一样的,看了你的帖子使我茅塞顿开
帮我大忙了,但是不知道为什么,原来的库不加也没事?