【玩转RT-Thread】CPK-RA6M4智慧门禁系统教学(下)

简介: 【玩转RT-Thread】CPK-RA6M4智慧门禁系统教学

3.3 RC522

3.3.1 底层SPI协议简介

SPI(Serial Peripheral Interface,串行外设接口)是一种高速、全双工、同步通信总线,常用于短距离通讯,主要应用于 EEPROM、FLASH、实时时钟、AD 转换器、还有数字信号处理器和数字信号解码器之间。SPI 一般使用 4 根线通信,如下图所示:

  • MOSI –主机输出 / 从机输入数据线(SPI Bus Master Output/Slave Input)。
  • MISO –主机输入 / 从机输出数据线(SPI Bus Master Input/Slave Output)。
  • SCLK –串行时钟线(Serial Clock),主设备输出时钟信号至从设备。
  • CS –从设备选择线 (Chip select)。也叫 SS、CSB、CSN、EN 等,主设备输出片选信号至从设备。

整体的传输大概可以分为以下几个过程:

(1)主机先将NSS信号拉低,这样保证开始接收数据;

(2)当接收端检测到时钟的边沿信号时,它将立即读取数据线上的信号,这样就得到了一位数据(1bit;由于时钟是随数据一起发送的,因此指定数据的传输速度并不重要,尽管设备将具有可以运行的最高速度。

(3)主机发送到从机时:主机产生相应的时钟信号,然后数据一位一位地将从MOSI信号线上进行发送到从机;

(4)主机接收从机数据:如果从机需要将数据发送回主机,则主机将继续生成预定数量的时钟信号,并且从机会将数据通过MISO信号线发送;

3.3.2 RC522读卡机制说明

首先来看下RC522与M1卡的通讯流程:

寻卡->防止卡片冲撞->选卡->休眠->发送0x40(7bit)->发送0x43->发送0xa0等4字节->发送0x00等18字节

  • 复位应答(Request):M1卡的通信协议和通信波特率是定义好的,当有卡片进入读卡器的工作范围时,读卡器要以特定的协议与卡片通信,从而确定卡片的卡型。
  • 防冲突机制(Anticollision Loop):当有多张卡片进入读写器操作范围时,会从中选择一张卡片进行操作,并返回选中卡片的序列号。
  • 选择卡片(Select Tag):选择被选中的卡的序列号,并同时返回卡的容量代码。
  • 三次相互确认(3 Pass Authentication):选定要处理的卡片后,读写器就要确定访问的扇区号,并且对扇区密码进行密码校验。在三次互相认证后就可以通过加密流进行通信。每次在选择扇区的时候都要进行扇区的密码校验。
  • 对数据块的操作:
    读(Read):读一个块的数据;
    写(Write):在一个块中写数据;
    加(Increment):对数据块中的数值进行加值;
    减(Decrement):对数据块中的数值进行减值;
    传输(Transfer):将数据寄存器中的内容写入数据块中;
    中止(Halt):暂停卡片的工作;
3.3.3 RC522在RT-Thread的使用

首先打开settings,添加RC522软件包,并在硬件部分使能SPI1

打开瑞萨FSP,添加一个名为r_spi的新stack,并进行如下配置:

引脚接线:

引脚功能 引脚接线
MOSI P411
MISO P410
SCL P412
SDA P311
RST P312
VCC 3.3V
GND GND
IRQ 悬空

代码部分参考RC522sample

SPI初始化配置:

#include "mfrc522.h"
static struct rt_spi_device mfrc522_spi_dev;
struct rt_hw_spi_cs
{
    rt_uint32_t pin;
};
static struct rt_hw_spi_cs spi_cs;
static int rt_hw_spi_rc522_init()
{
    rt_err_t res = RT_EOK;
    // Attach Device
    spi_cs.pin = MFRC522_SS_PIN;
    rt_pin_mode(spi_cs.pin, PIN_MODE_OUTPUT);
    res = rt_spi_bus_attach_device(&mfrc522_spi_dev, MFRC522_SPI_DEVICE_NAME, MFRC522_SPI_BUS_NAME, (void*)&spi_cs);
    if (res != RT_EOK)
    {
        rt_kprintf("[RC522] Failed to attach device %s\n", MFRC522_SPI_DEVICE_NAME);
        return res;
    }
    // Set device SPI Mode
    struct rt_spi_configuration cfg = {0};
    cfg.data_width = 8;
    cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB | RT_SPI_NO_CS;
    cfg.max_hz = MFRC522_SPICLOCK;
    rt_spi_configure(&mfrc522_spi_dev, &cfg);
    return RT_EOK;
}
/* 导出到自动初始化 */
INIT_COMPONENT_EXPORT(rt_hw_spi_rc522_init);

另外需要在完成一下配置,双击打开mfrc522.h,修改MFRC522_SS_PIN为0x3b,MFRC522_RST_PIN为0x3c,分别对应SDA和RST引脚

打开mfrc522.c,修改配置MFRC522_SS_PINMFRC522_RST_PIN

打开rtconfig.h,找到以下两个引脚的定义,修改成如下:

注意:一旦在RT-Thread settings中做了相关操作并保存设置后,在rtconfig.h中的配置都会以settings中的配置为准而被全部刷新,所以需要保留一个备份,下次保存设置的时候记得重新修改配置

#define MFRC522_SS_PIN 0x3b
#define MFRC522_RST_PIN 0x3c

至此,RC522的相关配置结束

3.4 SSD1306

3.4.1 底层I2C通信协议

(这里参考AHT10关于I2C通信协议的介绍,此处不再赘述)

3.4.2 SSD1306在RT-Thred的使用

接线示意:

引脚功能 引脚接线
SCL P400
SDA P401
VCC 3.3V
GND GND

RT-Thread Settings配置:

添加ssd1306软件包,然后跳转到配置界面修改i2c address为0x3c,bus name为i2c0

打开rtconfig.h,添加i2c代码,注意之前在rtconfig.h中进行的配置已经被刷新,需要重新添加配置代码

#define BSP_USING_I2C
#define BSP_USING_I2C0
#define BSP_I2C0_SCL_PIN 0x400
#define BSP_I2C0_SDA_PIN 0x401

打开drv_soft_i2c.c文件,添加代码:

#ifdef BSP_USING_I2C0
#define I2C0_BUS_CONFIG                                  \
    {                                                    \
        .scl = BSP_I2C0_SCL_PIN,                         \
        .sda = BSP_I2C0_SDA_PIN,                         \
        .bus_name = "i2c0",                              \
    }
#endif

打开瑞萨FSP,新建一个r_iic_master的new stack,完成以下配置:

生成配置之后添加用户代码:

#include "ssd1306.h"
void oled_init()
{
    ssd1306_Init();
    ssd1306_Fill(Black);
    ssd1306_SetCursor(10, 25);
    ssd1306_WriteString("Hello RT-Thread!", Font_7x10, White);
    ssd1306_UpdateScreen();
}
INIT_APP_EXPORT(oled_init);

实时时钟显示代码:

ssd1306_Fill(White);
            ssd1306_SetCursor(0, 5);
            ssd1306_WriteString("Now Time", Font_16x26, Black);
            ssd1306_SetCursor(40, 40);
            ssd1306_WriteString(mstr, Font_11x18, Black);
            ssd1306_SetCursor(50, 40);
            ssd1306_WriteString(":", Font_11x18, Black);
            ssd1306_SetCursor(60, 40);
            ssd1306_WriteString(hstr, Font_11x18, Black);
            ssd1306_UpdateScreen();

温湿度数据显示代码:

ssd1306_Fill(White);
            ssd1306_SetCursor(4, 2);
            ssd1306_WriteString("Humi_Temp_Detection!", Font_7x10, Black);
            ssd1306_UpdateScreen();
            rt_thread_mdelay(1000);
            char buff[64];
            snprintf(buff, sizeof(buff), "Temperature: %d.%d\n", (int)temperature, (int)(temperature * 10) % 10);
            ssd1306_SetCursor(15, 30);
            ssd1306_WriteString(buff, Font_6x8, Black);
            ssd1306_UpdateScreen();
            rt_kprintf("Temperature_OLED : %d.%d\n", (int)temperature, (int)(temperature * 10) % 10);
            snprintf(buff, sizeof(buff), "Humidity:%d.%d\n", (int)humidity, (int)(humidity * 10) % 10);
            ssd1306_SetCursor(25, 47);
            ssd1306_WriteString(buff, Font_6x8, Black);
            ssd1306_UpdateScreen();
            rt_kprintf("Humidity_OLED : %d.%d\n", (int)humidity, (int)(humidity * 10) % 10);

4、整体代码框架

4.1 多线程任务分配

本次细分作品功能,共分为四大模块:分别是AHT10温湿度读取、onenet上云、oled显示、rc522读卡。

所以共创建四个线程:

(1)RC522_thread:用于RC522读卡

(2)aht10_read_thread:用于aht10读取温湿度数值

(3)onenet_aht10_thread:云端数据上报

(4)oled_thread:OLED显示

4.2 线程间交互

本次在IPC方面的使用很不成熟,只是在每个线程的入口函数中进行互斥量的保护,并没有将RT-Thread内核机制灵活运用到代码中,是我此次学习的最大不足,其实也做过一些例如邮箱机制的使用,但是由于数据显示异常而没有进行下去,在工程源码的ITNG_Project2中包含了这种机制的使用,也就是说提供了两套方案,但是确实个人效率太低,第二种方案被搁置。

4.3 代码整合

在本次的程序设计中,我使用了一个while循环结合switch选择语句来保证整体代码的运行,在线程的入口程序使用互斥量来完成资源的保护,但是RT-Thread多线程机制的使用也是仍显不足。

都说程序设计也是艺术设计,要学会使用代码抽象人类社会的运行机制,程序设计方面,我设计的不合理,导致整个项目如同流水线般运行,亮点不大,值得反思。

5、踩坑指南

其实大部分踩坑说明在上面的教学指南中一般都有说明,这里简单说些:

(1)注意瑞萨FSP目前在RT-Thread中的支持包版本为v3.5.0

(2)由于瑞萨有自己完整的生态开发工具,所以RT-Thread与瑞萨合作时对于底层驱动的定义只有部分,还有一些需要在FSP中进行配置并生成配置。同时在HAL库中也需要添加相应的驱动代码,同时记得需要在settings中将相应的外设支持打开。

(3)对于每次的settings设置,其实都会生成相关的宏和定义在rtconfig.h文件中,所以每次更行settings时都会将用户在rtconfig.h中添加的代码删除,这时候需要重新添加,否则会生成一些宏未定义的错误。

目录
相关文章
|
6月前
|
存储 安全 数据可视化
GE PAC8000控制系统 I/O模块 —— 概述
GE PAC8000控制系统 I/O模块 —— 概述
|
3月前
|
存储 人机交互 语音技术
基于RT-Thread的智能家居助手
一、项目简介 智能家居助手主要基于RT-Thread开发的,该系统主要分为语音子系统,环境监测子系统,智能控制子系统,智能网关子系统,音乐播放器,云端以及应用软件七大部分。语音子系统可通过语音进行人机交互来控制家电设备。环境监测子系统为智能家居提供环境信息输入,实时监测室内的环境信息。智能控制子系统为智能家居提供控制接口,用户可根据实际需求来控制家电设备。 智能网关是整个系统的核心和枢纽,为整个智能家居提供网络,同时与云平台进行交互,不断更新室内信息,实时将数据上传至云端,用户就能在远程进行查室内的各种环境信息,实时掌握家中的最新动态。音乐播放器为用户提供音乐服务。云端部分为智能家居系统云
|
6月前
|
调度
【RT-Thread】学习日记之系统节拍Tick
【RT-Thread】学习日记之系统节拍Tick
|
6月前
|
编解码 开发工具 vr&ar
RT-Thread 瑞萨 智能家居网络开发:RA6M3 HMI Board 以太网+GUI技术实践
RT-Thread 瑞萨 智能家居网络开发:RA6M3 HMI Board 以太网+GUI技术实践
260 4
|
6月前
|
消息中间件 Linux 芯片
RT-Thread快速入门-体验RT-Thread
RT-Thread快速入门-体验RT-Thread
97 0
RT-Thread快速入门-体验RT-Thread
|
6月前
|
消息中间件 存储 Linux
RT-Thread快速入门-信号实现
RT-Thread快速入门-信号实现
88 0
创建RT-thread软件仿真工程 写RT-thread内核
创建RT-thread软件仿真工程 写RT-thread内核
|
数据安全/隐私保护
|
Windows
学生信息管理系统—优化总结part1
学生信息管理系统—优化总结part1
107 0
学生信息管理系统—优化总结part1
|
传感器 IDE Linux
RT-Thread ADC设备学习笔记
RT-Thread ADC设备学习笔记
131 0