【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
除了大家熟悉的ttl,其实485和can用的也很多。485多用于工业,can多用于汽车、航空和医疗,两者是非常有价值的。ttl和232虽然方便,但是容易受到干扰。比如假设旁边是一个运行的电机,那么传输的数据就容易受到影响。485和can则没有这方面的烦恼。485可能大家比较熟悉,毕竟本来就是ttl转变过来的,唯独can,其实学习的方法也很多。

1、利用loopback学习can
学习的时候,不用两块板子,不用canh和canl短接,利用自环就可以学习can。这种情况下,哪怕是最便宜的几块钱核心板,也能跑起来。
2、设计数据流转场景
这里设计的场景,就是板子借助于ttl,从上位机拿到数据,发送给can1,又从can1接收到数据,发回给上位机,就是这么一个过程。
3、利用ai生成代码
**如果自己不会写代码,其实问题也不大,可以通过ai生成代码,自己能看懂、会修改就行。**这里面为了方便,可能会涉及到uart和can的接收中断。
4、代码编译和测试
生成的代码主要有两个部分,一个是中断stm32f10x_it.c,
#include "stm32f10x.h"
#define FRAME_LEN 8
extern uint8_t g_uartRxBuf[FRAME_LEN];
extern uint8_t g_uartRxIndex;
extern uint8_t count;
extern CanTxMsg TxMessage;
extern CanRxMsg RxMessage;
extern void USART1_SendBuffer(uint8_t *,uint8_t);
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(
USART1,
USART_IT_RXNE)!=RESET)
{
g_uartRxBuf[g_uartRxIndex++] = USART_ReceiveData(USART1);
count += 1;
if(g_uartRxIndex>=FRAME_LEN)
{
uint8_t i;
g_uartRxIndex=0;
for(i=0;i<FRAME_LEN;i++)
TxMessage.Data[i]=g_uartRxBuf[i];
TxMessage.DLC = FRAME_LEN;
CAN_Transmit(
CAN1,
&TxMessage);
}
}
}
void USB_LP_CAN1_RX0_IRQHandler(void)
{
if(CAN_GetITStatus(
CAN1,
CAN_IT_FMP0)!=RESET)
{
CAN_Receive(
CAN1,
CAN_FIFO0,
&RxMessage);
USART1_SendBuffer(
RxMessage.Data,
RxMessage.DLC);
CAN_ClearITPendingBit(
CAN1,
CAN_IT_FMP0);
}
}
这部分直接替换原来的代码即可,还有就是main.c,
#include "stm32f10x.h"
#define FRAME_LEN 8
uint8_t g_uartRxBuf[FRAME_LEN];
uint8_t g_uartRxIndex = 0;
uint8_t count = 0;
CanTxMsg TxMessage;
CanRxMsg RxMessage;
void RCC_Config(void);
void GPIO_Config(void);
void NVIC_Config(void);
void USART1_Config(void);
void CAN1_Config(void);
void USART1_SendBuffer(uint8_t *buf,uint8_t len);
void RCC_Config(void)
{
RCC_APB2PeriphClockCmd(
RCC_APB2Periph_GPIOA |
RCC_APB2Periph_AFIO |
RCC_APB2Periph_USART1,
ENABLE);
RCC_APB2PeriphClockCmd(
RCC_APB2Periph_GPIOB,
ENABLE);
RCC_APB1PeriphClockCmd(
RCC_APB1Periph_CAN1,
ENABLE);
}
void GPIO_Config(void)
{
GPIO_InitTypeDef g;
g.GPIO_Speed = GPIO_Speed_50MHz;
g.GPIO_Pin = GPIO_Pin_12;
g.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &g);
g.GPIO_Pin = GPIO_Pin_9;
g.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,&g);
g.GPIO_Pin = GPIO_Pin_10;
g.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&g);
g.GPIO_Pin = GPIO_Pin_12;
g.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,&g);
g.GPIO_Pin = GPIO_Pin_11;
g.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&g);
}
void NVIC_Config(void)
{
NVIC_InitTypeDef n;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
n.NVIC_IRQChannel = USART1_IRQn;
n.NVIC_IRQChannelPreemptionPriority = 0;
n.NVIC_IRQChannelSubPriority = 0;
n.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&n);
n.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
n.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_Init(&n);
}
void USART1_Config(void)
{
USART_InitTypeDef u;
u.USART_BaudRate = 115200;
u.USART_WordLength = USART_WordLength_8b;
u.USART_StopBits = USART_StopBits_1;
u.USART_Parity = USART_Parity_No;
u.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
u.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1,&u);
USART_ITConfig(
USART1,
USART_IT_RXNE,
ENABLE);
USART_Cmd(USART1,ENABLE);
}
void CAN1_Config(void)
{
CAN_InitTypeDef c;
CAN_FilterInitTypeDef f;
CAN_DeInit(CAN1);
CAN_StructInit(&c);
c.CAN_Mode = CAN_Mode_LoopBack; // loopback setting here!!!
c.CAN_ABOM = ENABLE;
c.CAN_SJW = CAN_SJW_1tq;
c.CAN_BS1 = CAN_BS1_8tq;
c.CAN_BS2 = CAN_BS2_3tq;
c.CAN_Prescaler = 6;
CAN_Init(CAN1,&c);
f.CAN_FilterNumber = 0;
f.CAN_FilterMode = CAN_FilterMode_IdMask;
f.CAN_FilterScale = CAN_FilterScale_32bit;
f.CAN_FilterIdHigh = 0;
f.CAN_FilterIdLow = 0;
f.CAN_FilterMaskIdHigh = 0;
f.CAN_FilterMaskIdLow = 0;
f.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
f.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&f);
CAN_ITConfig(
CAN1,
CAN_IT_FMP0,
ENABLE);
}
void USART1_SendByte(uint8_t d)
{
USART_SendData(USART1,d);
while(
USART_GetFlagStatus(
USART1,
USART_FLAG_TXE)==RESET);
}
void USART1_SendBuffer(uint8_t *buf,uint8_t len)
{
uint8_t i;
for(i=0;i<len;i++)
USART1_SendByte(buf[i]);
}
int main(void)
{
RCC_Config();
GPIO_Config();
NVIC_Config();
USART1_Config();
CAN1_Config();
TxMessage.StdId = 0x100;
TxMessage.ExtId = 0;
TxMessage.IDE = CAN_ID_STD;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.DLC = FRAME_LEN;
while(1)
{
if(count < 125) GPIO_SetBits(GPIOB, GPIO_Pin_12);
else GPIO_ResetBits(GPIOB, GPIO_Pin_12);
}
}
5、测试方法
测试方法比较简单,就是找来xcom或者是sscom,循环输入,看看有没有循环接收。