51单片机.之i2c读写eproom

1、i2c读写eeproom

通过uart发送数据,单片机接收数据后,显示到lcd,并写到eeprom保存。每次开机时,读取eeprom保存的数据,显示到 lcd。

程序框架
1、i2c驱动时序
2、uart中断收发数据
3、eeprom读写驱动
4、lcd驱动
5、main 应用程序,定时器1s中断循环监控,uart是否有数据,有就显示到lcd,并写入eeprom。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
1、i2c.c

#include <reg52.h>
#include <intrins.h>#define I2CDelay()  {_nop_();_nop_();_nop_();_nop_();}
sbit I2C_SCL = P3^7;
sbit I2C_SDA = P3^6;/* 产生总线起始信号 */
void I2CStart()
{I2C_SDA = 1; //首先确保SDA、SCL都是高电平I2C_SCL = 1;I2CDelay();I2C_SDA = 0; //先拉低SDAI2CDelay();I2C_SCL = 0; //再拉低SCL
}
/* 产生总线停止信号 */
void I2CStop()
{I2C_SCL = 0; //首先确保SDA、SCL都是低电平I2C_SDA = 0;I2CDelay();I2C_SCL = 1; //先拉高SCLI2CDelay();I2C_SDA = 1; //再拉高SDAI2CDelay();
}
/* I2C总线写操作,dat-待写入字节,返回值-从机应答位的值 */
bit I2CWrite(unsigned char dat)
{bit ack;  //用于暂存应答位的值unsigned char mask;  //用于探测字节内某一位值的掩码变量for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行{if ((mask&dat) == 0)  //该位的值输出到SDA上I2C_SDA = 0;elseI2C_SDA = 1;I2CDelay();I2C_SCL = 1;          //拉高SCLI2CDelay();I2C_SCL = 0;          //再拉低SCL,完成一个位周期}I2C_SDA = 1;   //8位数据发送完后,主机释放SDA,以检测从机应答I2CDelay();I2C_SCL = 1;   //拉高SCLack = I2C_SDA; //读取此时的SDA值,即为从机的应答值I2CDelay();I2C_SCL = 0;   //再拉低SCL完成应答位,并保持住总线return (~ack); //应答值取反以符合通常的逻辑://0=不存在或忙或写入失败,1=存在且空闲或写入成功
}
/* I2C总线读操作,并发送非应答信号,返回值-读到的字节 */
unsigned char I2CReadNAK()
{unsigned char mask;unsigned char dat;I2C_SDA = 1;  //首先确保主机释放SDAfor (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行{I2CDelay();I2C_SCL = 1;      //拉高SCLif(I2C_SDA == 0)  //读取SDA的值dat &= ~mask; //为0时,dat中对应位清零elsedat |= mask;  //为1时,dat中对应位置1I2CDelay();I2C_SCL = 0;      //再拉低SCL,以使从机发送出下一位}I2C_SDA = 1;   //8位数据发送完后,拉高SDA,发送非应答信号I2CDelay();I2C_SCL = 1;   //拉高SCLI2CDelay();I2C_SCL = 0;   //再拉低SCL完成非应答位,并保持住总线return dat;
}
/* I2C总线读操作,并发送应答信号,返回值-读到的字节 */
unsigned char I2CReadACK()
{unsigned char mask;unsigned char dat;I2C_SDA = 1;  //首先确保主机释放SDAfor (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行{I2CDelay();I2C_SCL = 1;      //拉高SCLif(I2C_SDA == 0)  //读取SDA的值dat &= ~mask; //为0时,dat中对应位清零elsedat |= mask;  //为1时,dat中对应位置1I2CDelay();I2C_SCL = 0;      //再拉低SCL,以使从机发送出下一位}I2C_SDA = 0;   //8位数据发送完后,拉低SDA,发送应答信号I2CDelay();I2C_SCL = 1;   //拉高SCLI2CDelay();I2C_SCL = 0;   //再拉低SCL完成应答位,并保持住总线return dat;
}

2、eeprom.c

#include <reg52.h>extern void I2CStart();
extern void I2CStop();
extern unsigned char I2CReadACK();
extern unsigned char I2CReadNAK();
extern bit I2CWrite(unsigned char dat);/* E2读取函数,buf-数据接收指针,addr-E2中的起始地址,len-读取长度 */
void E2Read(unsigned char *buf, unsigned char addr, unsigned char len)
{do {                       //用寻址操作查询当前是否可进行读写操作I2CStart();if (I2CWrite(0x50<<1)) //应答则跳出循环,非应答则进行下一次查询{break;}I2CStop();} while(1);I2CWrite(addr);            //写入起始地址I2CStart();                //发送重复启动信号I2CWrite((0x50<<1)|0x01);  //寻址器件,后续为读操作while (len > 1)            //连续读取len-1个字节{*buf++ = I2CReadACK(); //最后字节之前为读取操作+应答len--;}*buf = I2CReadNAK();       //最后一个字节为读取操作+非应答I2CStop();
}
/* E2写入函数,buf-源数据指针,addr-E2中的起始地址,len-写入长度 */
void E2Write(unsigned char *buf, unsigned char addr, unsigned char len)
{while (len > 0){//等待上次写入操作完成do {                       //用寻址操作查询当前是否可进行读写操作I2CStart();if (I2CWrite(0x50<<1)) //应答则跳出循环,非应答则进行下一次查询{break;}I2CStop();} while(1);//按页写模式连续写入字节I2CWrite(addr);           //写入起始地址while (len > 0){I2CWrite(*buf++);     //写入一个字节数据len--;                //待写入长度计数递减addr++;               //E2地址递增if ((addr&0x07) == 0) //检查地址是否到达页边界,24C02每页8字节,{                     //所以检测低3位是否为零即可break;            //到达页边界时,跳出循环,结束本次写操作}}I2CStop();}
}

3、uart.c


#include <reg52.h>bit flagFrame = 0;  //帧接收完成标志,即接收到一帧新数据
bit flagTxd = 0;    //单字节发送完成标志,用来替代TXD中断标志位
unsigned char cntRxd = 0;   //接收字节计数器
unsigned char pdata bufRxd[64];  //接收字节缓冲区extern void UartAction(unsigned char *buf, unsigned char len);/* 串口配置函数,baud-通信波特率 */
void ConfigUART(unsigned int baud)
{SCON  = 0x50;  //配置串口为模式1TMOD &= 0x0F;  //清零T1的控制位TMOD |= 0x20;  //配置T1为模式2TH1 = 256 - (11059200/12/32)/baud;  //计算T1重载值TL1 = TH1;     //初值等于重载值ET1 = 0;       //禁止T1中断ES  = 1;       //使能串口中断TR1 = 1;       //启动T1
}
/* 串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度 */
void UartWrite(unsigned char *buf, unsigned char len)
{while (len--)  //循环发送所有字节{flagTxd = 0;      //清零发送标志SBUF = *buf++;    //发送一个字节数据while (!flagTxd); //等待该字节发送完成}
}
/* 串口数据读取函数,buf-接收指针,len-指定的读取长度,返回值-实际读到的长度 */
unsigned char UartRead(unsigned char *buf, unsigned char len)
{unsigned char i;if (len > cntRxd)  //指定读取长度大于实际接收到的数据长度时,{                  //读取长度设置为实际接收到的数据长度len = cntRxd;}for (i=0; i<len; i++)  //拷贝接收到的数据到接收指针上{*buf++ = bufRxd[i];}cntRxd = 0;  //接收计数器清零return len;  //返回实际读取长度
}
/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
void UartRxMonitor(unsigned char ms)
{static unsigned char cntbkp = 0;static unsigned char idletmr = 0;if (cntRxd > 0)  //接收计数器大于零时,监控总线空闲时间{if (cntbkp != cntRxd)  //接收计数器改变,即刚接收到数据时,清零空闲计时{cntbkp = cntRxd;idletmr = 0;}else                   //接收计数器未改变,即总线空闲时,累积空闲时间{if (idletmr < 30)  //空闲计时小于30ms时,持续累加{idletmr += ms;if (idletmr >= 30)  //空闲时间达到30ms时,即判定为一帧接收完毕{flagFrame = 1;  //设置帧接收完成标志}}}}else{cntbkp = 0;}
}
/* 串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用 */
void UartDriver()
{unsigned char len;unsigned char pdata buf[40];if (flagFrame) //有命令到达时,读取处理该命令{flagFrame = 0;len = UartRead(buf, sizeof(buf));  //将接收到的命令读取到缓冲区中UartAction(buf, len);  //传递数据帧,调用动作执行函数}
}
/* 串口中断服务函数 */
void InterruptUART() interrupt 4
{if (RI)  //接收到新字节{RI = 0;  //清零接收中断标志位if (cntRxd < sizeof(bufRxd)) //接收缓冲区尚未用完时,{                            //保存接收字节,并递增计数器bufRxd[cntRxd++] = SBUF;}}if (TI)  //字节发送完毕{TI = 0;   //清零发送中断标志位flagTxd = 1;  //设置字节发送完成标志}
}

4、lcd.c

#include <reg52.h>#define LCD1602_DB  P0
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_E  = P1^5;/* 等待液晶准备好 */
void LcdWaitReady()
{unsigned char sta;LCD1602_DB = 0xFF;LCD1602_RS = 0;LCD1602_RW = 1;do {LCD1602_E = 1;sta = LCD1602_DB; //读取状态字LCD1602_E = 0;} while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止
}
/* 向LCD1602液晶写入一字节命令,cmd-待写入命令值 */
void LcdWriteCmd(unsigned char cmd)
{LcdWaitReady();LCD1602_RS = 0;LCD1602_RW = 0;LCD1602_DB = cmd;LCD1602_E  = 1;LCD1602_E  = 0;
}
/* 向LCD1602液晶写入一字节数据,dat-待写入数据值 */
void LcdWriteDat(unsigned char dat)
{LcdWaitReady();LCD1602_RS = 1;LCD1602_RW = 0;LCD1602_DB = dat;LCD1602_E  = 1;LCD1602_E  = 0;
}
/* 设置显示RAM起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
void LcdSetCursor(unsigned char x, unsigned char y)
{unsigned char addr;if (y == 0)  //由输入的屏幕坐标计算显示RAM的地址addr = 0x00 + x;  //第一行字符地址从0x00起始elseaddr = 0x40 + x;  //第二行字符地址从0x40起始LcdWriteCmd(addr | 0x80);  //设置RAM地址
}
/* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
{LcdSetCursor(x, y);   //设置起始地址while (*str != '\0')  //连续写入字符串数据,直到检测到结束符{LcdWriteDat(*str++);}
}
/* 初始化1602液晶 */
void InitLcd1602()
{LcdWriteCmd(0x38);  //16*2显示,5*7点阵,8位数据接口LcdWriteCmd(0x0C);  //显示器开,光标关闭LcdWriteCmd(0x06);  //文字不动,地址自动+1LcdWriteCmd(0x01);  //清屏
}

5、main.c


#include <reg52.h>unsigned char T0RH = 0;  //T0重载值的高字节
unsigned char T0RL = 0;  //T0重载值的低字节void InitShowStr();
void ConfigTimer0(unsigned int ms);
extern void InitLcd1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
extern void E2Read(unsigned char *buf, unsigned char addr, unsigned char len);
extern void E2Write(unsigned char *buf, unsigned char addr, unsigned char len);
extern void UartDriver();
extern void ConfigUART(unsigned int baud);
extern void UartRxMonitor(unsigned char ms);
extern void UartWrite(unsigned char *buf, unsigned char len);void main()
{EA = 1;            //开总中断ConfigTimer0(1);   //配置T0定时1msConfigUART(9600);  //配置波特率为9600InitLcd1602();     //初始化液晶InitShowStr();     //初始显示内容while (1){UartDriver();  //调用串口驱动}
}
/* 处理液晶屏初始显示内容 */
void InitShowStr()
{unsigned char str[17];str[16] = '\0';         //在最后添加字符串结束符,确保字符串可以结束E2Read(str, 0x20, 16);  //读取第一行字符串,其E2起始地址为0x20LcdShowStr(0, 0, str);  //显示到液晶屏E2Read(str, 0x40, 16);  //读取第二行字符串,其E2起始地址为0x40LcdShowStr(0, 1, str);  //显示到液晶屏
}
/* 内存比较函数,比较两个指针所指向的内存数据是否相同,ptr1-待比较指针1,ptr2-待比较指针2,len-待比较长度返回值-两段内存数据完全相同时返回1,不同返回0 */
bit CmpMemory(unsigned char *ptr1, unsigned char *ptr2, unsigned char len)
{while (len--){if (*ptr1++ != *ptr2++)  //遇到不相等数据时即刻返回0{return 0;}}return 1;  //比较完全部长度数据都相等则返回1
}
/* 将一字符串整理成16字节的固定长度字符串,不足部分补空格out-整理后的字符串输出指针,in-待整理字符串指针 */
void TrimString16(unsigned char *out, unsigned char *in)
{unsigned char i = 0;while (*in != '\0')  //拷贝字符串直到输入字符串结束{*out++ = *in++;i++;if (i >= 16)    //当拷贝长度已达到16字节时,强制跳出循环{break;}}for ( ; i<16; i++)  //如不足16个字节则用空格补齐{*out++ = ' ';}*out = '\0';        //最后添加结束符
}
/* 串口动作函数,根据接收到的命令帧执行响应的动作buf-接收到的命令帧指针,len-命令帧长度 */
void UartAction(unsigned char *buf, unsigned char len)
{unsigned char i;unsigned char str[17];unsigned char code cmd0[] = "showstr1 ";  //第一行字符显示命令unsigned char code cmd1[] = "showstr2 ";  //第二行字符显示命令unsigned char code cmdLen[] = {           //命令长度汇总表sizeof(cmd0)-1, sizeof(cmd1)-1,};unsigned char code *cmdPtr[] = {          //命令指针汇总表&cmd0[0],  &cmd1[0],};for (i=0; i<sizeof(cmdLen); i++)  //遍历命令列表,查找相同命令{if (len >= cmdLen[i])  //首先接收到的数据长度要不小于命令长度{if (CmpMemory(buf, cmdPtr[i], cmdLen[i]))  //比较相同时退出循环{break;}}}switch (i) //根据比较结果执行相应命令{case 0:buf[len] = '\0';                   //为接收到的字符串添加结束符TrimString16(str, buf+cmdLen[0]);  //整理成16字节固定长度字符串LcdShowStr(0, 0, str);             //显示字符串1E2Write(str, 0x20, sizeof(str));   //保存字符串1,起始地址为0x20break;case 1:buf[len] = '\0';                   //为接收到的字符串添加结束符TrimString16(str, buf+cmdLen[1]);  //整理成16字节固定长度字符串LcdShowStr(0, 1, str);             //显示字符串1E2Write(str, 0x40, sizeof(str));   //保存字符串2,起始地址为0x40break;default:   //未找到相符命令时,给上机发送“错误命令”的提示UartWrite("bad command.\r\n", sizeof("bad command.\r\n")-1);return;}buf[len++] = '\r';  //有效命令被执行后,在原命令帧之后添加buf[len++] = '\n';  //回车换行符后返回给上位机,表示已执行UartWrite(buf, len);
}
/* 配置并启动T0,ms-T0定时时间 */
void ConfigTimer0(unsigned int ms)
{unsigned long tmp;  //临时变量tmp = 11059200 / 12;      //定时器计数频率tmp = (tmp * ms) / 1000;  //计算所需的计数值tmp = 65536 - tmp;        //计算定时器重载值tmp = tmp + 32;           //补偿中断响应延时造成的误差T0RH = (unsigned char)(tmp>>8);  //定时器重载值拆分为高低字节T0RL = (unsigned char)tmp;TMOD &= 0xF0;   //清零T0的控制位TMOD |= 0x01;   //配置T0为模式1TH0 = T0RH;     //加载T0重载值TL0 = T0RL;ET0 = 1;        //使能T0中断TR0 = 1;        //启动T0
}
/* T0中断服务函数,执行串口接收监控和蜂鸣器驱动 */
void InterruptTimer0() interrupt 1
{TH0 = T0RH;  //重新加载重载值TL0 = T0RL;UartRxMonitor(1);  //串口接收监控
}

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

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

相关文章

动手学深度学习(pytorch)学习记录19-参数管理[学习记录]

文章目录 参数访问目标参数一次性访问所有参数从嵌套块收集参数 参数初始化内置初始化自定义初始化 参数绑定延后初始化 本节内容&#xff1a; 访问参数&#xff0c;用于调试、诊断和可视化&#xff1b; 参数初始化&#xff1b; 在不同模型组件间共享参数&#xff1b; 延后初始…

第二证券:大牛股突发,停牌不超3天,此前22个涨停!

*ST富润晚间公告称&#xff0c;公司股票8月2日至9月3日已累计18个交易日涨停&#xff0c;股价涨幅为100.89%&#xff0c;股价不坚定较大&#xff0c;投资者较为重视。为保护投资者利益&#xff0c;公司姑息股票交易状况进行核对。经申请&#xff0c;公司股票自2024年9月4日开市…

给大模型加上“记忆”,深入探索 Mem0 项目

背景介绍 在之前的软件应用中&#xff0c;我们总会在应用中保留大量的用户历史操作记录&#xff0c;方便用户下次使用时可以快速查看和复用&#xff0c;甚至基于这些用户记录可以为用户提供个性化的服务。而这些记录往往都保存在传统的结构化或非结构化数据库中。 在大模型的…

JAVA毕业设计168—基于Java+Springboot+vue3的高校就业管理系统(源代码+数据库+14000字论文+开题+PPT)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootvue3的高校就业管理系统(源代码数据库14000字论文开题PPT)169 一、系统介绍 本项目前后端分离(可以改为ssm版本)&#xff0c;分为用户、企业、管理员三种角色 …

shopify独立站分别有哪几类?难点在哪?

对于刚开独立站的业内人士来说&#xff0c;今天的文章将向您介绍Shopify店铺的类型以及运营店铺的难点。这使您可以更好地计划销售哪些产品以及如何运营。 ✅Shopify 类型 综合商店&#xff1a;又称全能商店 这种类型通常采用直销模式。卖家不需要提供自己的产品。您可以选择…

git 配置、下载、提交、更新、冲突解决学习

目录 一. 安装教程 二. git配置 1. 查看git配置参数 2. 设置邮箱和用户名 3. SSH配置 4. 配置git远程库公钥 5. 编码设置 三. git 提交流程 1. 整体操作流程图 2. Git仓库包含5个区域 3. 下载、提交、更新命令 3.1. 下载 3.2. 提交 3.3. 更新&#xff08;两种方式…

前端框架有哪些?

成长路上不孤单&#x1f60a;【14后&#xff0c;C爱好者&#xff0c;持续分享所学&#xff0c;如有需要欢迎收藏转发&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#xff01;&#xff01;&#xff01;&#xff01;&#xff…

游戏应用|空地模型实景融合,还原《黑神话:悟空》游戏场景

古色斑驳&#xff0c;巍峨险峻&#xff0c;是历史的低语&#xff0c;诉说着千百年的沧桑与辉煌&#xff1b;飞檐翘角&#xff0c;雕梁画栋&#xff0c;凝聚着时代的文明与智慧。在数字化浪潮下&#xff0c;我们利用实景三维技术&#xff0c;翻开了中华古建筑这本伟大的史诗。 P…

基于物联网的低成本便携式传感器节点用于火灾和空气污染的检测与报警

目录 摘要 引言 材料和方法 传感器节点 IoT 微控制器 颗粒物传感器 环境和气体传感器 MQTT代理 Node-Red监控平台 系统结构 数据存储 工作描述 实验结果 讨论 结论 致谢 参考文献 这篇论文的标题是《Low-cost IoT-based Portable Sensor Node for Fire and Air…

【算法每日一练及解题思路】计算以空格隔开的字符串的最后一个单词的长度

【算法每日一练及解题思路】计算以空格隔开的字符串的最后一个单词的长度 一、题目&#xff1a;计算以空格隔开的字符串的最后一个单词的长度 二、举例&#xff1a; 输入&#xff1a;hello nowcoder 输出&#xff1a;8 说明&#xff1a;最后一个单词为nowcoder&#xff0c;长…

【超详细】Linux开发环境搭建指南 | Ubuntu

文章目录 虚拟机安装对比Virtual Box 下载ubuntu 操作系统下载Virtual Box 安装安装ubuntu设置中文语言共享文件夹设置添加输入法安装步骤&#xff0c;参考官方教程 安装 vscode解决主机不能通过ssh连接宿主机网络连接几种网络连接区别主机和宿主机相互 ping通 网络代理 虚拟机…

AI 网关基于 IP 地理位置,增强 Prompt 修饰能力

作者&#xff1a;沈鑫糠&#xff0c;来自昆仑数智瑞道云团队&#xff0c;专注于云原生领域产品研发和相关技术。 前言 什么是 Prompt Engineering 提示词工程&#xff08;Prompt Engineering&#xff09;&#xff0c;也被称为上下文提示&#xff08;In-Context Prompting&am…

云服务器+docker:还在为项目上线苦恼?一文包你解决(保姆级教程,图文并茂,万字起步!!!)

目录 Blue留言机&#xff1a; 学习视频以及参考资料 &#xff1a; 1、学习之前的必备操作&#xff1a; 第一步&#xff1a;购买服务器 选择一台免费的云服务器&#xff08;包白嫖的&#xff09; 配置服务器的一点说明&#xff1a; 查看自己是否购买成功&#xff1a; 第…

Codeforces Round 920 (Div. 3)(A,B,C,D)

A 在二维坐标轴上有一个正方形&#xff0c;给你一个正方形的四个顶点坐标&#xff0c;求面积 知道一个边长&#xff0c;平方即可 for(int i0;i<4;i)x[i]x1; Arrays.sort(x); //1122 kMath.abs(x[2]-x[1]); System.out.println(k*k); B 操作1、2是添加和修改&#xff0c;操…

Django+Vue二手交易平台的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 需要的环境3.2 Django接口层3.3 实体类3.4 config.ini3.5 启动类3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质创作者&…

ubuntu14.04.5出现配环境后重启进不了图形化界面解决记录

前言 这段时间给公司接了一个需要使用到linux环境进行交叉编译的工程&#xff0c;就采用了简单易操作的图形化ubuntu系统。 镜像采用的是&#xff1a;ubuntu14.04.5-desktop-amd64.iso(官网下载的&#xff09; 配置环境的过程下载了众多依赖包&#xff0c;总之就是缺啥下载啥…

vue通过html2canvas+jspdf生成PDF问题全解(水印,分页,截断,多页,黑屏,空白,附源码)

前端导出PDF的方法不多&#xff0c;常见的就是利用canvas画布渲染&#xff0c;再结合jspdf导出PDF文件&#xff0c;代码也不复杂&#xff0c;网上的代码基本都可以拿来即用。 如果不是特别追求完美的情况下&#xff0c;或者导出PDF内容单页的话&#xff0c;那么基本上也就满足业…

HOW DO VISION TRANSFORMERS WORK

HOW DO VISION TRANSFORMERS WORK Namuk Park1,2, Songkuk Kim1 1Yonsei University, 2NAVER AI Lab{namuk.park,songkuk}yonsei.ac.kr 总结 MSA 改善模型泛化能力&#xff1a; MSA 不仅提高了模型的准确性&#xff0c;还通过平滑损失景观来提高泛化能力。损失景观的平坦化使…

ArkUI-动画

ArkUI-动画 系统能力属性动画显式动画 关键帧动画转场动画路径动画粒子动画 资源调用GIF动画帧动画 三方库LottieSVG 提升动画的流畅度使用renderGroup概述使用约束 系统能力 属性动画 通过更改组件的属性值实现渐变过渡效果&#xff0c;例如缩放、旋转、平移等。支持的属性包…

乐鑫 ESP32-P4 无线连接解决方案

ESP32-P4 是乐鑫信息科技推出的一款功能强大的芯片 (SoC) &#xff0c;专为高性能的应用打造。尽管 ESP32-P4 集成了一系列先进特性&#xff0c;但它并未设置无线连接功能&#xff0c;因此需要额外的连接方案来满足嵌入式系统的多样化需求。乐鑫为 ESP32-P4 提供了三种主要的连…