ESP32从入门到精通之串口通信

串口通信

示例代码位置:examples/peripherals/uart/uart_echo

ESP32使用串口和指纹模块进行通信。电路图如下:

串口收发简单示例

我们先来写一个简单的串口示例程序。

#include"freertos/FreeRTOS.h"
#include"freertos/task.h"
#include"esp_system.h"
#include"esp_log.h"
#include"driver/uart.h"
#include"string.h"
#include"driver/gpio.h"

staticconstint RX_BUF_SIZE =1024;

#defineTXD_PIN(GPIO_NUM_21)
#defineRXD_PIN(GPIO_NUM_20)

voidinit(void)
{
constuart_config_t uart_config ={
.baud_rate =115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
// We won't use a buffer for sending data.
uart_driver_install(UART_NUM_1, RX_BUF_SIZE *2,0,0,NULL,0);
uart_param_config(UART_NUM_1,&uart_config);
uart_set_pin(UART_NUM_1, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}

intsendData(constchar*logName,constchar*data)
{
constint len =strlen(data);
constint txBytes =uart_write_bytes(UART_NUM_1, data, len);
ESP_LOGI(logName,"Wrote %d bytes", txBytes);
return txBytes;
}

staticvoidtx_task(void*arg)
{
staticconstchar*TX_TASK_TAG ="TX_TASK";
esp_log_level_set(TX_TASK_TAG, ESP_LOG_INFO);
while(1)
{
sendData(TX_TASK_TAG,"Hello world");
vTaskDelay(2000/ portTICK_PERIOD_MS);
}
}

staticvoidrx_task(void*arg)
{
staticconstchar*RX_TASK_TAG ="RX_TASK";
esp_log_level_set(RX_TASK_TAG, ESP_LOG_INFO);
uint8_t*data =(uint8_t*)malloc(RX_BUF_SIZE +1);
while(1)
{
constint rxBytes =uart_read_bytes(UART_NUM_1, data, RX_BUF_SIZE,1000/ portTICK_PERIOD_MS);
if(rxBytes >0)
{
            data[rxBytes]=0;
ESP_LOGI(RX_TASK_TAG,"Read %d bytes: '%s'", rxBytes, data);
ESP_LOG_BUFFER_HEXDUMP(RX_TASK_TAG, data, rxBytes, ESP_LOG_INFO);
}
}
free(data);
}

voidapp_main(void)
{
init();
xTaskCreate(rx_task,"uart_rx_task",1024*2,NULL, configMAX_PRIORITIES,NULL);
xTaskCreate(tx_task,"uart_tx_task",1024*2,NULL, configMAX_PRIORITIES -1,NULL);
}

有了以上的基础,我们就可以来实现指纹模块的驱动程序了。

指纹模块

我们先来写头文件

#ifndef__FINGERPRINT_DRIVER_H_
#define__FINGERPRINT_DRIVER_H_

#include"driver/uart.h"
#include"driver/gpio.h"

/// 下面的配置可以直接写死,也可以在 menuconfig 里面配置
#defineUART_TX_PIN21
#defineUART_RX_PIN20

#defineBUF_SIZE1024

#defineFINGER_TOUCH_INT10

/// 初始化指纹模块
voidFINGERPRINT_Init(void);

/// 获取指纹芯片的序列号
voidget_chip_sn(void);

/// 获取指纹图像
intget_image(void);

/// 获取指纹特征
intgen_char(void);

/// 搜索指纹
intsearch(void);

/// 读取指纹芯片配置参数
voidread_sys_params(void);

#endif

然后编写头文件中接口的实现

#include"fingerprint_driver.h"

voidFINGERPRINT_Init(void)
{
/* Configure parameters of an UART driver,
     * communication pins and install the driver */

uart_config_t uart_config ={
.baud_rate =57600,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,// 禁用奇偶校验
.stop_bits = UART_STOP_BITS_1,// 停止位1位
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
int intr_alloc_flags =0;

uart_driver_install(
        UART_NUM_1,
        BUF_SIZE *2,0,0,NULL,
        intr_alloc_flags);
uart_param_config(UART_NUM_1,&uart_config);
// 为串口1分配tx和rx引脚
uart_set_pin(
        UART_NUM_1,
        UART_TX_PIN,
        UART_RX_PIN,
        UART_PIN_NO_CHANGE,
        UART_PIN_NO_CHANGE);

// 中断
gpio_config_t io_conf;
    io_conf.intr_type = GPIO_INTR_NEGEDGE;
    io_conf.mode = GPIO_MODE_INPUT;
    io_conf.pin_bit_mask =(1ULL<< TOUCH_INT);
    io_conf.pull_up_en =1;
gpio_config(&io_conf);

printf("指纹模块初始化成功。\r\n");
}

voidget_chip_sn(void)
{
vTaskDelay(200/ portTICK_PERIOD_MS);
uint8_t*data =(uint8_t*)malloc(BUF_SIZE);

// 获取芯片唯一序列号 0x34。确认码=00H 表示 OK;确认码=01H 表示收包有错。
uint8_t PS_GetChipSN[13]={0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x04,0x34,0x00,0x00,0x39};
uart_write_bytes(UART_NUM_1,(constchar*)PS_GetChipSN,13);

// Read data from the UART
int len =uart_read_bytes(UART_NUM_1, data,(BUF_SIZE -1),2000/ portTICK_PERIOD_MS);

if(len)
{
if(data[6]==0x07&& data[9]==0x00)
{
printf("chip sn: %.32s\r\n",&data[10]);
}
}

free(data);
}

// 检测是否有手指放在模组上面
intget_image(void)
{
uint8_t*data =(uint8_t*)malloc(BUF_SIZE);

// 验证用获取图像 0x01,验证指纹时,探测手指,探测到后录入指纹图像存于图像缓冲区。返回确认码表示:录入成功、无手指等。
uint8_t PS_GetImageBuffer[12]={0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x03,0x01,0x00,0x05};

uart_write_bytes(UART_NUM_1,(constchar*)PS_GetImageBuffer,12);

int len =uart_read_bytes(UART_NUM_1, data,(BUF_SIZE -1),2000/ portTICK_PERIOD_MS);

int result =0xFF;

if(len)
{
if(data[6]==0x07)
{
if(data[9]==0x00)
{
                result =0;
}
elseif(data[9]==0x01)
{
                result =1;
}
elseif(data[9]==0x02)
{
                result =2;
}
}
}

free(data);

return result;
}

intgen_char(void)
{
uint8_t*data =(uint8_t*)malloc(BUF_SIZE);

// 生成特征 0x02,将图像缓冲区中的原始图像生成指纹特征文件存于模板缓冲区。
uint8_t PS_GenCharBuffer[13]={0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x04,0x02,0x01,0x00,0x08};

uart_write_bytes(UART_NUM_1,(constchar*)PS_GenCharBuffer,13);

int len =uart_read_bytes(UART_NUM_1, data,(BUF_SIZE -1),2000/ portTICK_PERIOD_MS);

int result =0xFF;

if(len)
{
if(data[6]==0x07)
{
            result = data[9];
}
}

free(data);

return result;
}

intsearch(void)
{
uint8_t*data =(uint8_t*)malloc(BUF_SIZE);

// 搜索指纹 0x04,以模板缓冲区中的特征文件搜索整个或部分指纹库。若搜索到,则返回页码。加密等级设置为 0 或 1 情况下支持此功能。
uint8_t PS_SearchBuffer[17]={0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x08,0x04,0x01,0x00,0x00,0xFF,0xFF,0x02,0x0C};

uart_write_bytes(UART_NUM_1,(constchar*)PS_SearchBuffer,17);

int len =uart_read_bytes(UART_NUM_1, data,(BUF_SIZE -1),2000/ portTICK_PERIOD_MS);

int result =0xFF;

if(len)
{
if(data[6]==0x07)
{
            result = data[9];
}
}

free(data);

return result;
}

voidread_sys_params(void)
{
uint8_t*data =(uint8_t*)malloc(BUF_SIZE);

// 获取模组基本参数 0x0F,读取模组的基本参数(波特率,包大小等)。参数表前 16 个字节存放了模组的基本通讯和配置信息,称为模组的基本参数。
uint8_t PS_ReadSysPara[12]={0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x03,0x0F,0x00,0x13};

uart_write_bytes(UART_NUM_1,(constchar*)PS_ReadSysPara,12);

int len =uart_read_bytes(UART_NUM_1, data,(BUF_SIZE -1),2000/ portTICK_PERIOD_MS);

if(len)
{
if(data[6]==0x07)
{
if(data[9]==0x00)
{
int register_count =(data[10]<<8)| data[11];
printf("register count ==> %d\r\n", register_count);
int fingerprint_template_size =(data[12]<<8)| data[13];
printf("finger print template size ==> %d\r\n", fingerprint_template_size);
int fingerprint_library_size =(data[14]<<8)| data[15];
printf("finger print library size ==> %d\r\n", fingerprint_library_size);
int score_level =(data[16]<<8)| data[17];
printf("score level ==> %d\r\n", score_level);
// device address
printf("device address ==> 0x");
for(int i =0; i <4; i++)
{
printf("%02X ", data[18+ i]);
}
printf("\r\n");
// data packet size
int packet_size =(data[22]<<8)| data[23];
if(packet_size ==0)
{
printf("packet size ==> 32 bytes\r\n");
}
elseif(packet_size ==1)
{
printf("packet size ==> 64 bytes\r\n");
}
elseif(packet_size ==2)
{
printf("packet size ==> 128 bytes\r\n");
}
elseif(packet_size ==3)
{
printf("packet size ==> 256 bytes\r\n");
}
// baud rate
int baud_rate =(data[24]<<8)| data[25];
printf("baud rate ==> %d\r\n",9600* baud_rate);
}
elseif(data[9]==0x01)
{
printf("send packet error\r\n");
}
}
}

free(data);
}

发表评论