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,循环输入,看看有没有循环接收。

相关推荐
zhangrelay3 小时前
新版|-|单片机原理与接口技术-2026持续改进优化-从MEGA2560-ESP32与Wokwi到ROS2-Lyrical与具身智能栈
笔记·单片机·嵌入式硬件·学习
叼烟扛炮7 小时前
Linux 学习笔记(三十三):线程互斥——互斥锁(Mutex)与死锁
linux·运维·服务器·笔记·学习·1024程序员节
m4Rk_9 小时前
【论文阅读】Agent 记忆机制(113):Agentic Memory Management——从“检索相关信息”走向“管理 Agent 内部记忆”
论文阅读·人工智能·学习·开源·github
辣知10 小时前
辣知·化智92 《山海经》里的史前密码
学习
鬼手点金10 小时前
KV Cache 未必是一次性的:可编辑、可组合的“笔记”
java·人工智能·笔记·学习·自动化·1024程序员节
kyrie_sakura12 小时前
大模型学习18 大模型学习 - LangChain2_Model I/O
学习·自然语言处理
宝绿特塑业再生科技12 小时前
板材收缩率不稳,户外家具装配尺寸为何对不上:从切割尺寸变化到接缝不一的系统性排查与对策
笔记·科技·学习·生活·户外家具·hdpe再生颗粒·hdpe
~城南花已开~13 小时前
Intel E810 SR-IOV VF Spoofcheck 防伪造测试-KVM3
服务器·网络·笔记·学习·ubuntu·etl工程师
我命由我1234515 小时前
6-3.Python 异常处理 - 异常处理进阶(else 块与 finally 块、异常传递、自定义异常)
开发语言·前端·数据库·后端·python·学习·java-ee
外收内放15 小时前
FastAPI猜字谜实战(8):收官
开发语言·python·学习·fastapi