STM32 与 AS608 指纹模块的调试与应用

前言

在嵌入式系统中,指纹识别作为一种生物识别技术,广泛应用于门禁系统、考勤机、智能锁等场景。本文将分享如何在 STM32F103C8T6 开发板上使用 AS608 指纹模块,实现指纹的录入和识别功能。
在这里插入图片描述

硬件准备

  • STM32F103C8T6 开发板
  • AS608 指纹模块
  • OLED 显示屏(用于显示提示信息)
  • 杜邦线若干

硬件连接

确保硬件连接正确,以下是主要的连接:

  • AS608 指纹模块与 STM32 的连接:

    • AS608 TXD(发送端) ==> STM32 PA3(USART2 RX)
    • AS608 RXD(接收端) ==> STM32 PA2(USART2 TX)
    • AS608 VCC ==> 3.3V
    • AS608 GND ==> GND
  • OLED 显示屏与 STM32 的连接:

    按照 OLED 屏幕的接线要求进行连接,一般使用 I2C 或 SPI 接口。

软件设计

项目结构

  • main.c:主程序入口,负责整体流程控制。
  • AS608.c / AS608.h:封装与 AS608 指纹模块的通信与操作函数。
  • 其他外设驱动文件:如 OLED 显示屏的驱动代码。

主程序流程

  1. 初始化外设:OLED 显示屏、USART2(用于与 AS608 通信)等。
  2. 等待 3 秒:给用户准备时间。
  3. 指纹录入
    • 提示用户放置手指。
    • 获取指纹图像,并生成特征文件。
    • 提示用户再次放置手指,重复上述步骤。
    • 合成指纹模板并存储到指纹库中。
  4. 等待 2 秒
  5. 指纹识别
    • 提示用户放置手指。
    • 获取指纹图像,生成特征文件。
    • 在指纹库中搜索匹配的指纹。
    • 显示识别结果(匹配的指纹 ID 或未找到)。

代码实现

1. main.c
#include "stm32f10x.h"
#include "Delay.h"
#include "OLED.h"
#include "AS608.h"int main(void)
{// 初始化外设OLED_Init();AS608_Init();OLED_ShowString(1, 1, "AS608:");while(1){Delay_s(3);  // 等待3秒OLED_ShowString(2, 1, "Enrolling...");if (AS608_Enroll() == 0){OLED_ShowString(2, 1, "Enroll OK    ");}else{OLED_ShowString(2, 1, "Enroll Failed");}Delay_s(2);  // 再等待2秒(总共5秒)OLED_ShowString(2, 1, "Identifying...");uint16_t id;if (AS608_Identify(&id) == 0){OLED_ShowString(2, 1, "ID:");OLED_ShowNum(2, 4, id, 5);}else{OLED_ShowString(2, 1, "Not Found    ");}Delay_s(2);  // 等待2秒显示结果}
}
2. AS608.h
#ifndef __AS608_H
#define __AS608_H#include "stm32f10x.h"// 指令代码
#define PS_GetImage          0x01
#define PS_GenChar           0x02
#define PS_Match             0x03
#define PS_Search            0x04
#define PS_RegModel          0x05
#define PS_StoreChar         0x06
#define PS_LoadChar          0x07
#define PS_UpChar            0x08
#define PS_DownChar          0x09
#define PS_UpImage           0x0A
#define PS_DownImage         0x0B
#define PS_DeleteChar        0x0C
#define PS_Empty             0x0D
#define PS_SetSysPara        0x0E
#define PS_ReadSysPara       0x0F
#define PS_SetPwd            0x12
#define PS_VerifyPwd         0x13
#define PS_TemplateNum       0x1D// 确认码
#define ACK_SUCCESS          0x00void AS608_Init(void);
uint8_t AS608_Enroll(void);
uint8_t AS608_Identify(uint16_t *id);#endif /* __AS608_H */
3. AS608.c
#include "AS608.h"
#include "Delay.h"
#include "OLED.h"
#include <stdio.h>void AS608_Init(void)
{// USART2 初始化RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 配置 USART2 引脚GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;  // TXGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;  // RXGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置 USART2USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 57600;  // AS608默认波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART2, &USART_InitStructure);USART_Cmd(USART2, ENABLE);
}void AS608_SendByte(uint8_t Byte)
{USART_SendData(USART2, Byte);while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
}void AS608_SendArray(uint8_t *Array, uint16_t Length)
{for (uint16_t i = 0; i < Length; i++){AS608_SendByte(Array[i]);}
}uint8_t AS608_ReceiveByte(void)
{uint32_t timeout = 0xFFFFF; // 增加超时时间while (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET){if (--timeout == 0){return 0xFF;  // 超时返回}}return USART_ReceiveData(USART2);
}// 发送指令包
void AS608_SendCommand(uint8_t instruction_code, uint8_t *parameters, uint16_t parameter_length)
{uint16_t packet_length = parameter_length + 2; // instruction code + parametersuint8_t packet[12 + parameter_length];uint16_t checksum = 0;// 包头packet[0] = 0xEF;packet[1] = 0x01;// 地址packet[2] = 0xFF;packet[3] = 0xFF;packet[4] = 0xFF;packet[5] = 0xFF;// 包标识packet[6] = 0x01; // 指令包// 包长度packet[7] = (packet_length >> 8) & 0xFF;packet[8] = packet_length & 0xFF;// 指令码packet[9] = instruction_code;// 参数for (uint16_t i = 0; i < parameter_length; i++){packet[10 + i] = parameters[i];}// 计算校验和checksum = packet[6] + packet[7] + packet[8];for (uint16_t i = 9; i < 10 + parameter_length; i++){checksum += packet[i];}// 校验和packet[10 + parameter_length] = (checksum >> 8) & 0xFF;packet[11 + parameter_length] = checksum & 0xFF;// 发送包AS608_SendArray(packet, 12 + parameter_length);
}// 接收响应包
uint8_t AS608_ReceivePacket(uint8_t *buffer, uint16_t *length)
{uint16_t idx = 0;uint16_t i;uint16_t checksum = 0;// 读取包头和地址,共6字节for (i = 0; i < 6; i++){buffer[idx++] = AS608_ReceiveByte();}// 检查包头和地址if (buffer[0] != 0xEF || buffer[1] != 0x01){return 1; // 包头错误}// 读取包标识和长度,共3字节for (i = 0; i < 3; i++){buffer[idx++] = AS608_ReceiveByte();}uint16_t packet_length = (((uint16_t)buffer[7] << 8) | buffer[8]) - 2; // 减去校验和长度// 读取包内容和校验和for (i = 0; i < packet_length + 2; i++){buffer[idx++] = AS608_ReceiveByte();}*length = idx;// 计算校验和for (i = 6; i < idx - 2; i++){checksum += buffer[i];}uint16_t received_checksum = ((uint16_t)buffer[idx - 2] << 8) | buffer[idx - 1];if (checksum != received_checksum){return 2; // 校验和错误}return 0; // 成功
}// 指纹录入函数
uint8_t AS608_Enroll(void)
{uint8_t ack;uint8_t buffer[64];uint16_t length;uint16_t page_id = 0; // 假设将指纹存储在ID为0的位置uint8_t retry;// 提示放置手指OLED_ShowString(2, 1, "Place Finger ");// Step 1: 获取图像retry = 0;do{AS608_SendCommand(PS_GetImage, NULL, 0);ack = AS608_ReceivePacket(buffer, &length);if (ack == 0 && buffer[9] == ACK_SUCCESS){break;}else if (ack == 0 && buffer[9] == 0x02){OLED_ShowString(3, 1, "No Finger    ");}else{OLED_ShowString(3, 1, "GetImage Err ");}Delay_ms(500);retry++;} while (retry < 10);if (retry >= 10){return 1; // 超时}// Step 2: 生成特征文件到CharBuffer1uint8_t param[1] = {0x01}; // Buffer1AS608_SendCommand(PS_GenChar, param, 1);ack = AS608_ReceivePacket(buffer, &length);if (ack != 0 || buffer[9] != ACK_SUCCESS){return 1; // 错误}// 提示移开手指OLED_ShowString(2, 1, "Remove Finger");Delay_s(2);// 提示再次放置手指OLED_ShowString(2, 1, "Place Again  ");// Step 3: 再次获取图像retry = 0;do{AS608_SendCommand(PS_GetImage, NULL, 0);ack = AS608_ReceivePacket(buffer, &length);if (ack == 0 && buffer[9] == ACK_SUCCESS){break;}Delay_ms(500);retry++;} while (retry < 10);if (retry >= 10){return 1; // 超时}// Step 4: 生成特征文件到CharBuffer2param[0] = 0x02; // Buffer2AS608_SendCommand(PS_GenChar, param, 1);ack = AS608_ReceivePacket(buffer, &length);if (ack != 0 || buffer[9] != ACK_SUCCESS){return 1; // 错误}// Step 5: 合并特征到模板AS608_SendCommand(PS_RegModel, NULL, 0);ack = AS608_ReceivePacket(buffer, &length);if (ack != 0 || buffer[9] != ACK_SUCCESS){return 1; // 错误}// Step 6: 存储模板到指定IDuint8_t store_param[3] = {0x01, (page_id >> 8) & 0xFF, page_id & 0xFF};AS608_SendCommand(PS_StoreChar, store_param, 3);ack = AS608_ReceivePacket(buffer, &length);if (ack != 0 || buffer[9] != ACK_SUCCESS){return 1; // 错误}return 0; // 成功
}// 指纹识别函数
uint8_t AS608_Identify(uint16_t *id)
{uint8_t ack;uint8_t buffer[64];uint16_t length;uint8_t retry;// 提示放置手指OLED_ShowString(2, 1, "Place Finger ");// Step 1: 获取图像retry = 0;do{AS608_SendCommand(PS_GetImage, NULL, 0);ack = AS608_ReceivePacket(buffer, &length);if (ack == 0 && buffer[9] == ACK_SUCCESS){break;}else if (ack == 0 && buffer[9] == 0x02){OLED_ShowString(3, 1, "No Finger    ");}else{OLED_ShowString(3, 1, "GetImage Err ");}Delay_ms(500);retry++;} while (retry < 10);if (retry >= 10){return 1; // 超时}// Step 2: 生成特征文件到CharBuffer1uint8_t param[1] = {0x01}; // Buffer1AS608_SendCommand(PS_GenChar, param, 1);ack = AS608_ReceivePacket(buffer, &length);if (ack != 0 || buffer[9] != ACK_SUCCESS){return 1; // 错误}// Step 3: 搜索指纹库uint8_t search_param[6] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x01}; // Buffer1, 起始页0,页数1AS608_SendCommand(PS_Search, search_param, 6);ack = AS608_ReceivePacket(buffer, &length);if (ack != 0 || buffer[9] != ACK_SUCCESS){return 1; // 未找到}// 获取匹配到的指纹ID*id = ((uint16_t)buffer[10] << 8) | buffer[11];return 0; // 成功
}

关键问题与解决方案

问题描述

在实现过程中,发现程序一直停留在 Place Finger 提示,无法继续。这表明程序可能在等待指纹模块的响应,但未能收到正确的数据。

可能原因
  1. USART 通讯问题

    • 波特率设置不正确。
    • USART 引脚连接错误。
    • USART 接收函数未正确实现。
  2. 指令包格式错误

    • 指令包中的参数、校验和计算错误。
    • 未正确按照 AS608 通讯协议发送和接收数据。
  3. 指纹模块未正常工作

    • 模块损坏或供电不足。
    • 指纹库已满或需要初始化。
解决方案
  1. 检查 USART 通讯配置

    • 确保波特率设置为 57600,这是 AS608 的默认波特率。

    • 检查 USART2 初始化代码,确保配置正确。

      // 配置 USART2
      USART_InitTypeDef USART_InitStructure;
      USART_InitStructure.USART_BaudRate = 57600;  // AS608默认波特率
      USART_InitStructure.USART_WordLength = USART_WordLength_8b;
      USART_InitStructure.USART_StopBits = USART_StopBits_1;
      USART_InitStructure.USART_Parity = USART_Parity_No;
      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
      USART_Init(USART2, &USART_InitStructure);
      
    • 确认引脚连接:

      • PA2(USART2 TX) ==> AS608 RXD
      • PA3(USART2 RX) ==> AS608 TXD
  2. 改进接收函数 AS608_ReceiveByte

    • 增加超时时间,避免因等待时间过短导致接收失败。

      uint8_t AS608_ReceiveByte(void)
      {uint32_t timeout = 0xFFFFF; // 增加超时时间while (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET){if (--timeout == 0){return 0xFF;  // 超时返回}}return USART_ReceiveData(USART2);
      }
      
  3. 检查指令包格式和校验和计算

    • 确保发送的指令包符合 AS608 通讯协议,包括包头、地址、包标识、包长度、指令码、参数、校验和。

    • 修改 AS608_SendCommand 函数中的校验和计算方式:

      // 计算校验和
      checksum = packet[6] + packet[7] + packet[8];
      for (uint16_t i = 9; i < 10 + parameter_length; i++)
      {checksum += packet[i];
      }
      
  4. 增加调试信息

    • 在关键步骤中,通过 OLED 显示接收到的确认码,便于判断问题所在。

      OLED_ShowString(3, 1, "Ack: ");
      OLED_ShowHexNum(3, 6, buffer[9], 2);
      
  5. 增加超时和错误处理机制

    • 在等待指纹输入和接收模块响应时,增加重试次数,避免程序陷入死循环。

      uint8_t retry = 0;
      do
      {// 发送指令并接收响应// ...retry++;
      } while (retry < 10);
      
  6. 检查指纹模块工作状态

    • 确认指纹模块的供电电压为 3.3V,且电源足够稳定。

    • 如果指纹库已满,尝试清空指纹库:

      uint8_t AS608_EmptyLibrary(void)
      {uint8_t buffer[32];uint16_t length;AS608_SendCommand(PS_Empty, NULL, 0);uint8_t ack = AS608_ReceivePacket(buffer, &length);if (ack == 0 && buffer[9] == ACK_SUCCESS){return 0; // 成功}else{return 1; // 失败}
      }
      
  7. 使用最小化测试代码进行验证

    • 编写简单的测试程序,仅发送 PS_GetImage 指令,查看是否能收到正确的响应。

      int main(void)
      {// 初始化外设OLED_Init();AS608_Init();OLED_ShowString(1, 1, "AS608 Test:");while(1){OLED_ShowString(2, 1, "Testing...   ");AS608_SendCommand(PS_GetImage, NULL, 0);uint8_t buffer[32];uint16_t length;uint8_t ack = AS608_ReceivePacket(buffer, &length);if (ack == 0){OLED_ShowString(3, 1, "Ack: ");OLED_ShowHexNum(3, 6, buffer[9], 2);if (buffer[9] == ACK_SUCCESS){OLED_ShowString(4, 1, "GetImage OK ");}else{OLED_ShowString(4, 1, "GetImage Fail");}}else{OLED_ShowString(3, 1, "No Response  ");}Delay_s(2);}
      }
      

总结

通过对硬件连接、USART 通讯配置、指令包格式、接收函数以及错误处理机制的逐一检查和改进,成功实现了 AS608 指纹模块在 STM32 上的指纹录入和识别功能。

在调试过程中,遇到类似的问题时,应从硬件和软件两个方面入手,逐步排查。同时,增加调试信息和错误处理机制,可以大大提高调试效率。

注意事项

  • 确保指纹模块的电源供电稳定。
  • 遵循 AS608 通讯协议,正确组建指令包和解析响应包。
  • USART 接收函数需要考虑超时和异常情况。

参考资料

  • AS608 指纹模块数据手册
  • STM32F10x 标准外设库参考手册
  • UART 通讯协议和调试方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/65457.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3GPP R18 MT-SDT

Rel-17 指定MO-SDT允许针对UL方向的数据包进行小数据包传输。对于DL,MT-SDT(即DL触发的小数据)可带来类似的好处,即 通过不转换到 RRC_CONNECTED来减少信令开销和UE功耗,并通过允许快速传输(小而少见的)数据包(例如用于定位)来减少延迟。 在R17中,NR_SmallData_INACTIVE的工…

小程序基础 —— 02 微信小程序账号注册

微信小程序账号注册 小程序开发与网页开发不一样&#xff0c;在开始微信小程序开发之前&#xff0c;需要访问微信公众平台&#xff0c;注册一个微信小程序账号。 有了小程序的账号以后&#xff0c;才可以开发和管理小程序&#xff0c;后续需要通过该账号进行开发信息的设置、…

两个链表的第一个公共结点

输入两个链表&#xff0c;找出它们的第一个公共结点。 当不存在公共节点时&#xff0c;返回空节点。 数据范围 链表长度 [1,2000] 保证两个链表不完全相同&#xff0c;即两链表的头结点不相同。 算法思想描述 如上图所示&#xff0c;两种链表的出现的情况只有图中2中&…

OpenAI 12天发布会:AI革命的里程碑@附35页PDF文件下载

在人工智能的浪潮中&#xff0c;OpenAI的12天发布会无疑是2024年科技界的一场盛宴。从12月5日开始&#xff0c;OpenAI连续12天每天发布一个新应用或功能&#xff0c;标志着AI技术的又一次飞跃。本文将梳理这些激动人心的发布&#xff0c;带你一探究竟。 OpenAI发布会概览 Ope…

理解数列和函数的极限

什么是数列 数列就是按照1定顺序排列的数字&#xff0c; 也可以理解为包含数字元素的队列 格式: a 1 , a 2 , a 3 , . . . , a n a_1, a_2, a_3, ..., a_n a1​,a2​,a3​,...,an​, n ∈ N n \in N n∈N 或者 { a n } \{ a_n \} {an​}, n ∈ N n \in N n∈N 其中 a n…

TOP K问题:利用堆排序找出数组中最小的k个数

设计一个算法&#xff0c;找出数组中最小的k个数。以任意顺序返回这k个数均可。 找小的数需要建大堆来解决&#xff0c;首先将数组中前K个数建成一个大堆&#xff0c;将从k1个数直到数组结束的所有数与堆顶的数进行比较&#xff0c;如果比堆顶的数小&#xff0c;则替换堆顶的数…

6-Gin 路由详解 --[Gin 框架入门精讲与实战案例]

Gin 是一个用 Go 语言编写的 HTTP Web 框架&#xff0c;以其高性能和简洁的 API 而闻名。它提供了一套强大的路由功能&#xff0c;使得开发者可以轻松地定义 URL 路由规则&#xff0c;并将这些规则映射到具体的处理函数&#xff08;handler&#xff09;。以下是关于 Gin 路由的…

【数据库初阶】Linux中库的基础操作

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; 数据库初阶 &#x1f389;其它专栏&#xff1a; C初阶 | C进阶 | 初阶数据结构 亲爱的小伙伴们&#xff0c;大家好&#xff01;在这篇文章中&#xff0c;我们将深入浅出地为大家讲解 Linux…

【机器学习(九)】分类和回归任务-多层感知机(Multilayer Perceptron,MLP)算法-Sentosa_DSML社区版 (1)11

文章目录 一、算法概念11二、算法原理&#xff08;一&#xff09;感知机&#xff08;二&#xff09;多层感知机1、隐藏层2、激活函数sigma函数tanh函数ReLU函数 3、反向传播算法 三、算法优缺点&#xff08;一&#xff09;优点&#xff08;二&#xff09;缺点 四、MLP分类任务实…

【LLM】OpenAI 的DAY12汇总和o3介绍

note o3 体现出的编程和数学能力&#xff0c;不仅达到了 AGI 的门槛&#xff0c;甚至摸到了 ASI&#xff08;超级人工智能&#xff09;的边。 Day 1&#xff1a;o1完全版&#xff0c;开场即巅峰 12天发布会的开场即是“炸场级”更新——o1完全版。相比此前的预览版本&#x…

MaixBit k210学习记录

开发背景&#xff1a;Window系统主机&#xff0c;在主机上安装了虚拟机&#xff08;VirtualBoxUbuntu23.04&#xff09; 目标实现&#xff1a;在虚拟机&#xff08;Ubuntu&#xff09;中&#xff0c;实现对Maix bit&#xff08;k210&#xff09;开发板的开发 虚拟机的安装参考…

ExpDemo-JavaFX打造属于你自己的图形化漏洞利用工具

声明&#xff01;本文章所有的工具分享仅仅只是供大家学习交流为主&#xff0c;切勿用于非法用途&#xff0c;如有任何触犯法律的行为&#xff0c;均与本人及团队无关&#xff01;&#xff01;&#xff01; 目录标题 前言编写属于你的图像化漏洞利用工具项目结构编写EXP部署 部…

串口通信标准RS232、RS422、RS485有什么区别和不同

目录 第一个区别&#xff1a;硬件管脚接口定义不同&#xff1a; 第二个区别、工作方式不同 第三个区别、通信方式不同 第四个区别&#xff0c;逻辑特性不同 第五个区别、抗干扰性、传输距离和传输速率也不同 RS-232与RS-485对比 RS-422与RS-485对比 今天给大家分享的是&…

银河麒麟操作系统安装达梦数据库(超详细)

目录 引言1. 前期准备1.1 安装麒麟系统1.2 下载达梦数据库安装包&#xff08;DM8&#xff09;1.3 上传安装包到麒麟系统1.4 挂载安装包&#xff08;iso&#xff09;文件1.5 配置安装用户和组1.6 创建安装路径及修改权限1.7 设置临时安装目录 2. 安装达梦数据库&#xff08;DM8&…

Linux-frp_0.61.1内网穿透的配置和使用

下载frp frp官网 https://gofrp.org/zh-cn/docs/setup/ frp安装包下载地址 https://github.com/fatedier/frp/releases?page1 下载之后在服务器上 解压 tar -zxvf frp_0.61.1_linux_amd64.tar.gztar&#xff1a;一个用于压缩和解压缩的工具。-z&#xff1a;表示使用 gzi…

04.HTTPS的实现原理-HTTPS的混合加密流程

04.HTTPS的实现原理-HTTPS的混合加密流程 简介1. 非对称加密与对称加密2. 非对称加密的工作流程3. 对称加密的工作流程4. HTTPS的加密流程总结 简介 主要讲述了HTTPS的加密流程&#xff0c;包括非对称加密和对称加密两个阶段。首先&#xff0c;客户端向服务器发送请求&#xf…

【从零开始入门unity游戏开发之——C#篇34】C#匿名函数(delegate )和Lambda表达式

文章目录 一、匿名函数&#xff08;delegate &#xff09;1、什么是匿名函数&#xff1f;2、匿名函数的基本语法2.1 语法2.2 **没有参数的匿名函数&#xff1a;**2.3 **有参数的匿名函数&#xff1a;**2.4 **有返回值的匿名函数&#xff1a;** 3、匿名函数的使用示例3.1 作为参…

IDEA开发Java应用的初始化设置

一、插件安装 如下图所示&#xff1a; 1、Alibaba Java Coding Guidelines 2.1.1 阿里开发者规范&#xff0c;可以帮忙本地自动扫描出不符合开发者规范的代码&#xff0c;甚至是代码漏洞提示。 右击项目&#xff0c;选择《编码规约扫描》&#xff0c;可以进行本地代码规范扫…

代码模拟打字机(python)

回车符\r打印稿纸&#xff0c;time.sleep模拟停顿效果&#xff0c;一顿一顿的打字机效果就此呈现。 (笔记模板由python脚本于2024年12月27日 19:34:37创建&#xff0c;本篇笔记适合有基础编程能力的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.…

让 AMD GPU 在大语言模型推理中崭露头角:机遇与挑战

在当今科技飞速发展的时代&#xff0c;大语言模型&#xff08;LLM&#xff09;的兴起彻底改变了人工智能领域的格局。从智能客服到文本生成&#xff0c;从知识问答到代码编写辅助&#xff0c;大语言模型的应用无处不在&#xff0c;深刻影响着我们的生活和工作。然而&#xff0c…