esp32开发与应用(利用loopback学习can)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱: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,循环输入,看看有没有循环接收。

相关推荐
xianrenli382 小时前
DS5900作业之“氛围(Vibe)”背后的伦理
学习·ai编程·msai
iuu_star2 小时前
Python大模型智能学习平台——设计与实现(AI教学系统)
大数据·人工智能·python·学习
三品吉他手会点灯3 小时前
嵌入式机器学习 - 学习笔记1.2.3 - 机器学习软件框架
人工智能·笔记·嵌入式硬件·学习·机器学习
YangYang9YangYan4 小时前
2026数字经济专业毕业发展指南
物联网·学习
武陵悭臾5 小时前
Python应用开发学习:如何让随机数按一定比列出现
python·学习·random·概率·随机数
渣渣灰飞5 小时前
MySQL 系统学习 第六阶段:Redis + 缓存 + 高并发设计 第八章:Redis 高级应用
学习·mysql·缓存
Kobebryant-Manba5 小时前
学习Bert
学习·自然语言处理·bert
渣渣灰飞5 小时前
MySQL 系统学习 第六阶段:Redis + 缓存 + 高并发设计 第十章:Redis 综合企业项目实战
学习·mysql·缓存
xian_wwq6 小时前
【学习笔记】多模态部署:VLM、语音、视频理解(29/35)
笔记·学习·音视频