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

相关推荐
xian_wwq1 小时前
【学习笔记】-深度认知系列-第2讲-大模型到底是什么?——拆解“参数、训练、推理”
笔记·学习·深度认知
lzhdim3 小时前
12、JavaScript常见的内存泄露问题 - JavaScript学习系列文章
开发语言·前端·javascript·学习·ecmascript
那年窗外下的雪.4 小时前
AIDC 学习日志|第 15 天|EVPN 多归属故障收敛与撤销机制
网络·学习·php
M78佐菲5 小时前
Linux学习笔记:进程
linux·笔记·学习·算法
我命由我123457 小时前
人脸识别 - 勒克斯(光线照射到物体表面上的明亮程度)
android·java·学习·java-ee·人脸识别·学习方法·android runtime
Logintern098 小时前
【每天学习一点点】MPI是什么?
学习·mpi·多机训练
fengci.8 小时前
提示词注入学习小结
学习
晓梦林8 小时前
Tools2靶场学习笔记
笔记·学习
paopaokaka_luck10 小时前
基于springboot3+vue3的车间生产管理系统(Echarts图形化分析、BI报表)
java·前端·spring boot·学习·echarts
Canmag 兴隆磁性10 小时前
自动磁场分布测试+镭雕设备 AT-C
学习·永磁材料·磁场分布测试