DS1302时钟芯片全解析——概况,性能,MCU连接,样例代码

news2024/11/17 15:26:43

DS1302概述:

数据:

DS1302是一个可充电实时时钟芯片,包含时钟(24小时格式或12小时格式)、日历(年,月,日,星期)、31字节RAM(断电数据丢失)。

供电:

DS1302采用两组供电,一组主电,由外部供电,一组备电,一般由纽扣电池供电。当主电存在时,由主电供电,当主电不存在时由备电供电。

功能:

DS1302,通过外部晶振自动对时间进行计数,对月末日期进行调整,以及闰年矫正。MCU可对其时间日期进行设置及读取,显示正确的当前时间。同时可借用31字节的RAM临时保存重要数据(因为外部断电后,纽扣电池供电保证数据不丢失)。

连接:

与MCU连接只需要三个普通GPIO口即可,DS1302芯片的通讯方式接近于SPI,其中将SPI的MISO和MOSI合并为I/O引脚。但是并不需要使用SPI复用引脚进行连接,只需要普通GPIO引脚即可。

DS1302型号说明:

在这里插入图片描述
这里是常用国产有替代型号:DS1302,插件;DS1302Z+T,贴片;DS1302N温度范围从(0 ~ +70℃)提高到 (-40~ +85℃),插件;DS1302ZN+T温度范围从(0 ~ +70℃)提高到 (-40~ +85℃),贴片。

DS1302引脚说明:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

MCU连接:

正常使用时完全可以安照下图进行连接,非常简单,任意的3个GPIO口连接CE、I/O、SCLK(这里的SCLK只是提供一个上升沿做时钟信号,设低再设高之后数据即被DS1302读取,并非SPI或IIC的CLK)。晶振直接近距离连接DS1302即可,不需要接对地的匹配电容。VCC2接外部供电,VCC1接纽扣电池。
在这里插入图片描述
下图,晶振近距离连接DS1302,斜线部分的不要走信号线,会对晶振信号产生影响。
在这里插入图片描述

DS1302寄存器定义:

在这里插入图片描述

首先是寄存器地址:

寄存地址最后一位表示读写,前边按正常数值。如秒钟地址,读地址为0b1000 0001 = 0x81;写地址为0b1000 0000 = 0x80,所以读地址比写地址大1。

寄存器定义:

一个字节的8位二进制数分为十位和个位,并不是直接对应的十六进制数,这点要注意。例如23秒,读出的是0x23,而不是0x17。采用右移和与运算可对数据进行分离。
控制寄存器进行写保护操作,只对最高位写保护为进行操作即可。

RAM操作:

和时间寄存器一样,最后一位表示读写,前边按正常数值。如RAM 0地址,读地址为0b1100 0001 = 0xC1;写地址为0b1100 0000 = 0xC0。数据内容不限,任意单字节数值。

DS1302寄存器读写:

在这里插入图片描述
首先是读写时序图:
RST 即CE,为数据传输控制,数据传输时设高电平,不用时设低电平;
SCLK即DS1302 读写数值控制信号,上升沿触发, 即SCLK的GPIO由低电平设置到高电平时,DS1302读取或写出一个数据。
I/O即DS1302读取或写出的数据。在MCU写入数据时,连接的GPIO设置为一般输出模式,通过高低电平切换,写入数据;在MCU写入数据时,连接的GPIO设置为一般读取电平模式,通过获取DS1302 I/O输出的高低电平,读取数据。
I/O数据的寄存器地址由低位到高位的顺序进行写入;数据也是由低位到高位写入,或读出。 其中R/W 即为读写控制位0为读,1为写,A0-A4为地址数据,R/C为时间寄存器还是RAM寄存器控制位,D0-D7为写入数据,读取时该位置为读出数据。
在进行写时间数据操作时,MCU先向DS1302输出写寄存器地址,再紧跟着输出时间数据;在进行读时间数据操作时,MCU先向DS1302输出读寄存器地址,再紧跟着读取DS1302输出的时间数据;该数据输入输出流程时序由SCLK上升沿控制。

DS1302代码样例(基于HC32L130):

ds1302.h文件

#ifndef __DS1302_H__
#define __DS1302_H__

#include "ddl.h"
#include "gpio.h"
#include "hc32l13x.h"

//DS1302 GPIO定义
#define DS1302_RSTPORT				GpioPortB
#define	DS1302_RSTPIN					GpioPin12
#define	DS1302_DATAPORT				GpioPortB
#define	DS1302_DATAPIN				GpioPin11
#define	DS1302_CLKPORT				GpioPortB
#define	DS1302_CLKPIN					GpioPin10
//DS1302地址定义
#define ds1302_sec_add			  0x80		//秒数据地址
#define ds1302_min_add			  0x82		//分数据地址
#define ds1302_hr_add			    0x84		//时数据地址
#define ds1302_date_add			  0x86		//日数据地址
#define ds1302_month_add		  0x88		//月数据地址
#define ds1302_day_add			  0x8a		//星期数据地址
#define ds1302_year_add			  0x8c		//年数据地址
#define ds1302_control_add		0x8e		//控制数据地址
#define ds1302_charger_add		0x90 					 
#define ds1302_clkburst_add		0xbe
//初始时间定义
extern	uint8_t time_buf[8]; //设置时间
extern	uint8_t readtime[14];//当前时间

void ds1302_init(void);
void ds1302ioinit(void);

void ds1302_write_byte(uint8_t data);
uint8_t ds1302_read_byte(void);

void ds1302_write_reg_byte(uint8_t addr,uint8_t	data);
uint8_t ds1302_read_reg_byte(uint8_t addr);

void ds1302_read_time(void);
void ds1302_write_time(void);

uint8_t	ds1302_read_hour(void);
uint8_t	ds1302_read_minute(void);
uint8_t	ds1302_read_second(void);

#endif /* __DS1302_H__ */

ds1302.c文件

#include "ds1302.h"
#include "hc32l13x.h"

//定义GPIO操作
#define DS1302_SCK_PIN_LOW 		Gpio_ClrIO(DS1302_CLKPORT,DS1302_CLKPIN)
#define DS1302_SCK_PIN_HIGH 	Gpio_SetIO(DS1302_CLKPORT,DS1302_CLKPIN)

#define DS1302_RST_PIN_LOW 		Gpio_ClrIO(DS1302_RSTPORT,DS1302_RSTPIN)
#define DS1302_RST_PIN_HIGH 	Gpio_SetIO(DS1302_RSTPORT,DS1302_RSTPIN)

#define DS1302_SDA_PIN_LOW		Gpio_ClrIO(DS1302_DATAPORT,DS1302_DATAPIN)
#define DS1302_SDA_PIN_HIGH		Gpio_SetIO(DS1302_DATAPORT,DS1302_DATAPIN)
#define DS1302_SDA_PIN_READ		Gpio_GetInputIO(DS1302_DATAPORT,DS1302_DATAPIN)

//GPIO定义 SCLK和RST(CE)
void	ds1302ioinit(void) 
{
		stc_gpio_cfg_t         GpioInitStruct;	
		DDL_ZERO_STRUCT(GpioInitStruct);  
		///< 打开GPIO外设时钟门控
		Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);

		///< 端口驱动能力配置->低驱动能力
		GpioInitStruct.enDrv = GpioDrvL;
		///< 端口方向配置->输出
    GpioInitStruct.enDir = GpioDirOut;
		///< 端口上下拉配置->下拉
		GpioInitStruct.enPu = GpioPuDisable;
    GpioInitStruct.enPd = GpioPdEnable;

		///< 端口输出关闭
    Gpio_ClrIO(DS1302_CLKPORT, DS1302_CLKPIN);
    Gpio_ClrIO(DS1302_RSTPORT, DS1302_RSTPIN);

		///< 端口初始化
		Gpio_Init(DS1302_CLKPORT,DS1302_CLKPIN,&GpioInitStruct);
		Gpio_Init(DS1302_RSTPORT,DS1302_RSTPIN,&GpioInitStruct);
}

//GPIO定义 I/O输出
void	ds1302_dataOut_init(void)
{
		stc_gpio_cfg_t         GpioInitStruct;	
		DDL_ZERO_STRUCT(GpioInitStruct);  
		///< 打开GPIO外设时钟门控
		Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);

		///< 端口驱动能力配置->低驱动能力
		GpioInitStruct.enDrv = GpioDrvL;
		///< 端口方向配置->输出
    GpioInitStruct.enDir = GpioDirOut;
		///< 端口上下拉配置->下拉
		GpioInitStruct.enPu = GpioPuDisable;
    GpioInitStruct.enPd = GpioPdEnable;
    
    ///< 端口输出关闭
    Gpio_ClrIO(DS1302_DATAPORT, DS1302_DATAPIN);
		///< 端口初始化
		Gpio_Init(DS1302_DATAPORT,DS1302_DATAPIN,&GpioInitStruct);
}
//GPIO定义 I/O输入
void	ds1302_dataIn_init(void)
{
		stc_gpio_cfg_t         GpioInitStruct;	
		DDL_ZERO_STRUCT(GpioInitStruct);  
		///< 打开GPIO外设时钟门控
		Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
		
		///< 端口驱动能力配置->低驱动能力
		GpioInitStruct.enDrv = GpioDrvL;
		///< 端口方向配置->输入
    GpioInitStruct.enDir = GpioDirIn;
		///< 端口上下拉配置->无
		GpioInitStruct.enPu = GpioPuDisable;
		GpioInitStruct.enPd = GpioPdDisable;
		///< 端口开漏输出配置->开漏输出关闭
    GpioInitStruct.enOD = GpioOdDisable;
    ///< 端口输入/输出值寄存器总线控制模式配置->AHB
    GpioInitStruct.enCtrlMode = GpioAHB;

		Gpio_Init(DS1302_DATAPORT,DS1302_DATAPIN,&GpioInitStruct);               ///< 端口初始化
}

//DS1302初始化函数
void ds1302_init(void) 
{
		ds1302ioinit();
		ds1302_dataOut_init();
}

//向DS1302写入一字节数据
void ds1302_write_byte(uint8_t data) 
{
	uint8_t i;

	ds1302_dataOut_init();
	for (i = 0; i < 8; i ++) 
	{
		DS1302_SCK_PIN_LOW;
		if (data & 0x01) 
				DS1302_SDA_PIN_HIGH;
		else
				DS1302_SDA_PIN_LOW;
		DS1302_SCK_PIN_HIGH;
		data = data >> 1;
	}
}

//从DS1302读出一字节数据
uint8_t ds1302_read_byte(void)
{
	uint8_t i, data = 0;
	ds1302_dataIn_init();
	for (i = 0; i < 8; i ++)
	{
			DS1302_SCK_PIN_LOW;
			data >>= 1;
			if(DS1302_SDA_PIN_READ)
					data |= 0x80;
			DS1302_SCK_PIN_HIGH;
	}
	return data;
}

//向DS1302写入对应寄存器数据
void ds1302_write_reg_byte(uint8_t addr,uint8_t	data)
{
    DS1302_RST_PIN_LOW;
    DS1302_SCK_PIN_LOW;
    DS1302_RST_PIN_HIGH;
    ds1302_write_byte(addr);
    ds1302_write_byte(data);
    DS1302_SCK_PIN_HIGH;
    DS1302_RST_PIN_LOW;
}

//从DS1302读出对应寄存器数据
uint8_t ds1302_read_reg_byte(uint8_t addr)
{
    uint8_t data;
	
    DS1302_RST_PIN_LOW;
    DS1302_SCK_PIN_LOW;
    DS1302_RST_PIN_HIGH;
    ds1302_write_byte(addr);
    data=ds1302_read_byte();
    DS1302_SCK_PIN_HIGH;
    DS1302_RST_PIN_LOW;
    return data;
}

//向DS1302写入时间数据
void ds1302_write_time(void) 
{
	ds1302_write_reg_byte(ds1302_control_add,0x00);			//关闭写保护 
	ds1302_write_reg_byte(ds1302_charger_add,0x00);	    		//禁止充电 

	ds1302_write_reg_byte(ds1302_year_add,time_buf[1]);		//年 
	ds1302_write_reg_byte(ds1302_month_add,time_buf[2]);	//月 
	ds1302_write_reg_byte(ds1302_date_add,time_buf[3]);		//日 
	ds1302_write_reg_byte(ds1302_hr_add,time_buf[4]);		//时 
	ds1302_write_reg_byte(ds1302_min_add,time_buf[5]);		//分
	ds1302_write_reg_byte(ds1302_sec_add,time_buf[6]);		//秒
	ds1302_write_reg_byte(ds1302_day_add,time_buf[7]);		//周 

	ds1302_write_reg_byte(ds1302_control_add,0x80);			//打开写保护     
}

//从DS1302读出时间数据
void ds1302_read_time(void)  
{
	time_buf[1]=ds1302_read_reg_byte(ds1302_year_add+1);		//年 
	time_buf[2]=ds1302_read_reg_byte(ds1302_month_add+1);		//月 
	time_buf[3]=ds1302_read_reg_byte(ds1302_date_add+1);		//日 
	time_buf[4]=ds1302_read_reg_byte(ds1302_hr_add+1);		  //时 
	time_buf[5]=ds1302_read_reg_byte(ds1302_min_add+1);		  //分 
	time_buf[6]=(ds1302_read_reg_byte(ds1302_sec_add+1))&0x7f;//秒,屏蔽秒的第7位,避免超出59
	time_buf[7]=ds1302_read_reg_byte(ds1302_day_add+1);		  //周 	
	
	readtime[0]=(time_buf[0]>>4);   //分离出年千位
  readtime[1]=(time_buf[0]&0x0F); //分离出年百位 
  readtime[2]=(time_buf[1]>>4);   //分离出年十位
  readtime[3]=(time_buf[1]&0x0F); //分离出年个位 
  readtime[4]=(time_buf[2]>>4);   //分离出月十位
  readtime[5]=(time_buf[2]&0x0F); //分离出月个位 
  readtime[6]=(time_buf[3]>>4);   //分离出日十位
  readtime[7]=(time_buf[3]&0x0F); //分离出日个位 
  readtime[8]=(time_buf[4]>>4);   //分离出小时十位
  readtime[9]=(time_buf[4]&0x0F); //分离出小时个位 
  readtime[10]=(time_buf[5]>>4);   //分离出分钟十位
  readtime[11]=(time_buf[5]&0x0F); //分离出分钟个位
  readtime[12]=(time_buf[6]>>4);   //分离出秒钟十位
  readtime[13]=(time_buf[6]&0x0F); //分离出秒钟个位 
}

//从DS1302读出小时数据
uint8_t	ds1302_read_hour(void)
{
	uint8_t	time_hour;
	time_buf[4]=ds1302_read_reg_byte(ds1302_hr_add+1);		  //时
	readtime[8]=(time_buf[4]>>4);   //分离出小时十位
  readtime[9]=(time_buf[4]&0x0F); //分离出小时个位 
	time_hour = readtime[8]*10+readtime[9];
	return	time_hour;
}

//从DS1302读出分钟数据
uint8_t	ds1302_read_minute(void)
{
	uint8_t	time_minute;
	time_buf[5]=ds1302_read_reg_byte(ds1302_min_add+1);		  //分
	readtime[10]=(time_buf[5]>>4);   //分离出分钟十位
  readtime[11]=(time_buf[5]&0x0F); //分离出分钟个位 
	time_minute = readtime[10]*10+readtime[11];
	return	time_minute;
}

//从DS1302读出秒钟数据
uint8_t	ds1302_read_second(void)
{
	uint8_t	time_second;
	time_buf[6]=(ds1302_read_reg_byte(ds1302_sec_add+1))&0x7f;//秒,屏蔽秒的第7位,避免超出59
	readtime[12]=(time_buf[6]>>4);   //分离出秒钟十位
  readtime[13]=(time_buf[6]&0x0F); //分离出秒钟个位 
	time_second = readtime[12]*10+readtime[13];
	return	time_second;
}

main.c文件

#include "gpio.h"
#include "ddl.h"
#include "ds1302.h"

//读写时间列表定义
uint8_t time_buf[8]; //设置时间
uint8_t readtime[14];//当前时间

//读取时间
uint8_t ds1302_hour = 0;
uint8_t ds1302_minute = 0;
uint8_t ds1302_second = 0;

void init()
{
		time_buf[0] = 0x00;		//年 
		time_buf[1] = 0x24;		//年 
		time_buf[2] = 0x07;		//月 
		time_buf[3] = 0x19;		//日 
		time_buf[4]	= 0x17;		//时 
		time_buf[5] = 0x16;		//分
		time_buf[6]	= 0x20;		//秒
		time_buf[7] = 0x05;		//周 
}


int main(void)
{
		init();
		//DS1302初始化
		ds1302_init();
		//DS1302写入时间数据
		ds1302_write_time();

		while(1)
		{
				ds1302_hour = ds1302_read_hour();					//读取小时数据
				ds1302_minute = ds1302_read_minute();			//读取分钟数据
				ds1302_second	= ds1302_read_second();			//读取秒钟数据
				//DS1302读取时间数据
				ds1302_read_time();
		}
}

调试效果:
在这里插入图片描述

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

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

相关文章

【Test】 Qt 多元素控件

文章目录 1. Qt 中的多元素控件2. QListWidget 1. Qt 中的多元素控件 xxWidget 和 xxView之间的区别 2. QListWidget 小案例&#xff1a;实现下图

WSL快速入门

1. WSL介绍 WSL文档地址&#xff1a;https://learn.microsoft.com/zh-cn/windows/wsl WSL&#xff1a;全称 Windows Subsystem for Linux&#xff0c;即windows上的Linux子系统&#xff08;虚拟机工具&#xff09;。是Win10推出的全新特性&#xff0c;可以更轻量地在Windows系统…

R语言统计分析——整合和重构

参考资料&#xff1a;R语言实战【第2版】 R中提供了许多用来整合&#xff08;aggregate&#xff09;和重塑&#xff08;reshape&#xff09;数据的强大方法。在整合数据时&#xff0c;往往将多组观测替换为根据这些观测计算的描述性统计量。在重塑数据时&#xff0c;则会通过修…

【Unity插件】Editor Console Pro:提升开发效率的神器

在 Unity 开发过程中&#xff0c;控制台&#xff08;Console&#xff09;是我们排查错误、获取信息的重要窗口。而 Editor Console Pro 则是 Unity 编辑器控制台的强大替代品&#xff0c;为 Unity 的控制台带来了更多实用的功能和改进&#xff0c;极大地提升了开发效率。 一、…

[硬件]-电路噪声

电路噪声 1.电路噪声来源 本征噪声&#xff1a;晶体管、电阻&#xff1b;外部噪声&#xff1a;电源、参考、偏置、衬底、串扰&#xff1b; 将电路的输入短接&#xff0c;理想情况下输出为0&#xff0c;但实际输出不为0&#xff0c;即为电路噪声。 2.噪声大小衡量方法 2.1 时…

【Oracle 进阶之路】Oracle 简介

一、简述 Oracle Database&#xff0c;又名Oracle RDBMS&#xff0c;或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是世界上流行的关系数据库管理系统&#xff0c;系统可移植性好、使用方便、功能强&…

初学Mybatis之多对一查询 association 和一对多查询 collection

XML 映射器 多对一&#xff1a;关联&#xff08;association&#xff09; 一对多&#xff1a;集合&#xff08;collection&#xff09; mysql 创建教师、学生表&#xff0c;插入数据 create table teacher(id int(10) primary key,name varchar(30) default null ) engineI…

Meta 发布地表最大、最强大模型 Llama 3.1

最近这一两周看到不少互联网公司都已经开始秋招提前批了。不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。 最近&#xff0c;我们又陆续整理了很多大厂的面试题&#xff0c;帮助一些球友解…

简单几步,把浏览器书签转换成导航网页

废话不多说直奔主题上干货 Step 1 下载浏览器书签 1&#xff0c;电脑浏览器点击下载Pintree Pintree 是一个开源项目&#xff0c;旨在将浏览器书签导出成导航网站。通过简单的几步操作&#xff0c;就可以将你的书签转换成一个美观且易用的导航页面。 2. 安装 Pintree B…

《Java初阶数据结构》----10.<Map和Set---TreeSet和TreeMapHashSet和HashMap >

前言&#xff1a; 大家好&#xff0c;我目前在学习java。我准备利用这个暑假&#xff0c;来复习之前学过的内容&#xff0c;并整理好之前写过的博客进行发布。如果博客中有错误或者没有读懂的地方。热烈欢迎大家在评论区进行讨论&#xff01;&#xff01;&#xff01; 喜欢我文…

高并发内存池(四)Page Cache的框架及内存申请实现

目录 一、Page Cache的框架梳理 二、Page Cache的实现 2.1PageCache.h 2.2VirtualAlloc 2.3std::unordered_map _idSpanMap,> 2.4Page Cache.cpp 一、Page Cache的框架梳理 申请内存&#xff1a; 1. 当central cache向page cache申请内存时&#xff0c;page cache先检…

2024年7月29日 十二生肖 今日运势

小运播报&#xff1a;2024年7月29日&#xff0c;星期一&#xff0c;农历六月廿四 &#xff08;甲辰年辛未月甲午日&#xff09;&#xff0c;法定工作日。 红榜生肖&#xff1a;羊、虎、狗 需要注意&#xff1a;兔、牛、鼠 喜神方位&#xff1a;东北方 财神方位&#xff1a;…

论文阅读:Deformable DETR: Deformable Transformers for End-to-End Object Detection

论文阅读&#xff1a;Deformable DETR: Deformable Transformers for End-to-End Object Detection Deformable DETR: 基于稀疏空间采样的注意力机制&#xff0c;让DCN与Transformer一起玩&#xff01; - 知乎 (zhihu.com) 【Deformable DETR 论文源码解读】Deformable Trans…

Linux嵌入书学习—数据结构——栈(seqstak)

一、栈&#xff1b; 定义&#xff1a; 是限定仅在表尾&#xff08;栈顶&#xff09;进行插入和删除操作的线性表 栈又称为 后进先出&#xff08;Last In First Out&#xff09; 的线性表&#xff0c;简称 LIFO 结构 栈顶&#xff08;Top&#xff09; 栈顶是栈中允许进行添加&…

构建大规模账号池与本地部署:GitHub爬虫项目详解

账号池搭建 必要性 常见登录方式&#xff1a; 基于Session Cookie的登录基于JWT的登录&#xff1a;登录生成JWT字符串 账号池存储cookie或者JWT字符串 方便后续发请求爬取数据 本地部署 conda建立一个虚拟环境 conda create -n new_env python3.x # 替换 x 为你需要的 P…

【 C++ 】 类和对象的学习

前言&#xff1a; &#x1f618;我的主页&#xff1a;OMGmyhair-CSDN博客 目录 引言&#xff1a; 一、类的作用域 二、计算类对象的大小 三、this指针 this指针❓1 this指针❓2 this指针❓3 引言&#xff1a; 通过类我们可以对数据和方法进行封装 封装的意义&#xf…

【Android】实现一个优雅的自定义底部导航栏(速通安卓大作业必备)

文章目录 前言一、实现思路二、代码实现流程①修改theme&#xff1a;②在color文件中添加颜色&#xff1a;③添加图标文件④添加选中时布局的背景⑤修改布局文件⑥按钮效果图&#xff1a;⑦修改MainActivity中的代码⑦创建各个界面的Fragment⑧运行结果&#xff1a; 三、 总结 …

【学术会议征稿】第五届人工智能与教育国际学术会议(ICAIE 2024)

第五届人工智能与教育国际学术会议&#xff08;ICAIE 2024&#xff09; 2024 5th International Conference on Artificial Intelligence and Education 第五届人工智能与教育国际学术会议&#xff08;ICAIE 2024&#xff09;由集美大学诚毅学院主办&#xff0c;闽南师范大学…

福昕PDF编辑器v13专业版 授权版

福昕高级PDF编辑器是一款功能强大的PDF文件编辑软件&#xff0c;提供多种实用的编辑功能。 软件截图&#xff1a; 使用说明&#xff1a; 解压后&#xff0c;双击start.bat来运行软件 下载地址&#xff1a;FoxitPDFEditor-Pro-v13 解压密码&#xff1a;helloh 下载时可能会有…

动手学大模型应用开发笔记--用dash开发一个大模型知识库

简介 动手学&#xff0c;把自己学到的东西动手自己做出来并输出&#xff0c;是最好的学习方式。最近一直在关注和使用各种ai工具&#xff0c;也在学一些ai开发的知识&#xff0c;看到datawhale的开源学习教程&#xff0c;动手学大模型开发( [github.com/datawhalech…])这个教…