模板: RS485 CAN Shield for use

来自Waveshare Wiki
跳转至: 导航搜索

准备工作

  • RS485 CAN Shield 模块两个
  • STM32 开发板两个(本手册用的是微雪电子的 Xnucleo 开发板,主控芯片是 STM32F103R)
  • 杜邦线若干

跳线说明

  • D14(PB_9)、D15(PB_8)分别作为默认 CAN 的发送端和接收端。

注:PB_9,PB_8 作为 STM32 CAN1 管脚时编程需打开管脚重映射。

GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);
  • D7(PA_8)是 RS485 的发送接收使能端,高电平时为发送状态,低电平时为接收状态。
  • D8(PA_9)、D2(PA_10)和 D0(PA_2)、D1(PA_3)分别是 UART1 和 UART2 的发送端和接收端。可
  • 通过 485 RXD/TXD JMP 跳线帽选择 UART1 或 UART2 作为 RS485 的输出输入端。

注:Xnucleo 默认 PA_2、PA_3 作为串口转 USB 端口。若要用 D0、D1 作为 RS485 的串口,则还需变换 Xnucleo 中 JP4 相应跳线。用跳线帽将 1、3 管脚短接,2、4 管脚短接。Xuncleo原理图中 JP4 串口跳线如下图所示: RS485 CAN Shield 1.jpg

  • 模块间通信,CAN 端口的 H,L 分别和另一个模块的 CAN 端口 H,L 对接。RS485 端口的 A,B 分别和另一个模块的 RS485 端口 A,B 对接。

硬件连接

STM32连接引脚对应关系
Shield STM32 功能
VCC 3.3V 电源输入
GND GND 电源地
D2 PA10 RS485接收端
D8 PA9 RS485发送端
D7 PA8 RS485 发送接收使能端
D14 PB9 CAN发送端
D15 PB8 CAN接收端

D0、D1 将信息输出到 PC 端的串口。

软件工作原理

本测试程序采用 mbed 框架+STM32 库函数的形式,分为发送程序和接收程序两个程序。
CAN:
CAN 驱动程序采用 STM32 库函数编写,封装在 CAN.cpp 和 CAN.h 两个文件中。程序开始调用 CAN
初始化函数 CAN_Config()配置相关寄存器。
发送程序将要发送的数据保存在发送邮箱(TxMessage)中,再调用驱动函数
CAN_Transmit(CAN1, &TxMessage)发送出去。
而接收程序侧调用 CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);将接收到的数据保存
在接收邮箱(RxMessage)中。
RS485:
发送端程序控制 RS485_E 为高电平,使 RS485 处于发送状态,通过 RS485.printf 函数让数据
通过 RS485 串口发送出去。而接收程序则开启接收中断,程序控制 RS485_E 为低电平,使 RS485
处于接收状态,中断服务函数通过 RS485.scanf 扫描接收到的数据。

代码简介

发送端程序说明

/*CAN:程序开始调用 CAN 初始化函数,配置相关寄存器。CAN 通信侧建立一个发送邮箱 TXMsg,
将要发送的数据保存在邮箱中,再调用驱动函数发送出去。
RS485:控制 RS485_E 为高电平,使 RS485 处于发送状态,通过连接到 RS485 的串口将数据发送
出去。*/
#include "mbed.h"
#include "CAN.h"
Serial pc(D1,D0); //serial print message
Serial RS485(D8, D2); //RS485_TX RS485_RX
DigitalOut RS485_E(D7); //RS485_E
CanTxMsg TxMessage;
uint8_t TransmitMailbox = 0;
int i =0,j=0;
int main() {
CAN_Config();//CAN initialize
RS485_E = 1;//The RS485 transmission status was enabled
/* TxMessage */ //Set the mailbox data to be sent
TxMessage.StdId = 0x10;
TxMessage.ExtId = 0x1234;
TxMessage.RTR=CAN_RTR_DATA;
TxMessage.IDE=CAN_ID_STD;
TxMessage.DLC=8;
TxMessage.Data[0] = 'C';
TxMessage.Data[1] = 'A';
TxMessage.Data[2] = 'N';
TxMessage.Data[3] = ' ';
TxMessage.Data[4] = 'T';
TxMessage.Data[5] = 'e';
TxMessage.Data[6] = 's';
TxMessage.Data[7] = 't';
pc.printf( "**** This is a RS485_CAN_Shield Send test program
****\r\n");
while(1) {
RS485.printf("ncounter=%d ",j);//RS485 Transmit Data
wait(1);
TransmitMailbox = CAN_Transmit(CAN1, &TxMessage);//CAN Transmit Data
i = 0;
while((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK) &&
(i != 0xFFF)){
i++;
}
if(i == 0xFFF){
pc.printf("\r\can send fail\r\n");//Failed to send the packet due to timeout. Procedure
}
else{
pc.printf("\r\nCAN send TxMessage successfully \r\n");
//send successful
}
pc.printf("\r\nRS485 send: counter=%d\r\n",j++);//Print sending content
pc.printf("The CAN TxMsg: %s\r\n",TxMessage.Data);
wait(1);
} 
}

接收端程序说明

/*CAN:程序开始调用 CAN 初始化函数,配置相关寄存器。接收端查询 FIFO 中是否有数据,有的
话,则将接收到的数据保存到接收邮箱 RxMessage 中,再通过串口打印出来。
RS485:使能 RS485 接收中断函数,控制 RS485_E 为低电平,使 RS485 处于接收状态,中断服务
函数通过 RS485.scanf 扫描接收到的数据。*/
#include "mbed.h"
#include "CAN.h"
Serial pc(D1,D0); //serial print message
Serial RS485(D8, D2); //RS485_TX RS485_RX
DigitalOut RS485_E(D7); //RS485_E
CanRxMsg RxMessage; //RxMessage
char s[1024];
void callback()//RS485 Receive interrupt handler function
{// Note: you need to actually read from the serial to clear the RX interrupt
RS485.scanf("%s",s);//Save received data
pc.printf("\r\nRS485 Receive:%s \r\n",s);//Print receiving information
}
int main() {
CAN_Config();//CAN initialize
RS485.attach(&callback);//Enable RS485 receiving interruption
RS485_E = 0;//The receiving status was enabled
pc.printf( "**** This is a can receive test program ****\r\n");
while(1) {
while(CAN_MessagePending(CAN1, CAN_FIFO0) < 1)//Waiting for data to arrive
{
}
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//CAN Receive Data
pc.printf("The CAN RxMsg: %s\r\n",RxMessage.Data);//Print received data
}
}

实验现象

发送端串口输出:
RS485 CAN Shield 3.jpg

接收端串口输出:
RS485 CAN Shield 4.jpg