STM32F1之OV7725摄像头·SCCB总线详解(附带源码编写)

STM32F1之OV7725摄像头-CSDN博客

STM32F1之OV7725摄像头·像素数据输出时序、FIFO 读写时序以及摄像头的驱动原理详解-CSDN博客

目录

1.  硬件设计

1.1  SCCB 控制相关

1.2  VGA 时序相关

1.3  FIFO 相关

1.4  XCLK 信号

2.  代码设计

2.1  SCCB总线软件实现

2.1.1  宏定义

2.1.2  SCCB管脚配置

2.1.3  延时函数

2.1.4  SCCB起始信号

2.1.5  SCCB终止信号

2.1.6  SCCB应答信号

2.1.7  SCCB非应答信号

2.1.8  SCCB等待应答信号

2.1.9  发送数据

2.1.10  SCCB总线返回的数据

2.1.11  SCCB写一个字节数据

2.1.12  SCCB读一串数据


1.  硬件设计

        摄像头与 STM32 连接关系中主要分为 SCCB 控制、VGA 时序控制、FIFO 数据读取部分,介绍如下:

1.1  SCCB 控制相关

        摄像头中的 SIO_C 和 SIO_D 引脚直接连接到 STM32 普通的 GPIO,它们不具有硬件I2C 的功能,所以在后面的代码中采用模拟 I2C 时序,实际上直接使用硬件 I2C 是完全可以实现 SCCB 协议的,本设计采用模拟 I2C 是芯片资源分配妥协的结果。

1.2  VGA 时序相关

        检测 VGA 时序的 HREF、VSYNC 引脚,它们与 STM32 连接的 GPIO 均设置为输入模式,其中 HREF 在本实验中并没有使用,它已经通过摄像头内部的与非门控制了 FIFO 的写使能;VSYNC 与 STM32 连接的 GPIO 引脚会在程序中配置成中断模式,STM32 利用该中断信号获知新的图像是否采集完成,从而控制 FIFO 是否写使能。

1.3  FIFO 相关

        与 FIFO 控制相关的 RCLK、RRST、WRST、WEN 及 OE 与 STM32 连接的引脚均直接配置成推挽输出,STM32 根据图像的采集情况利用这些引脚控制 FIFO;读取 FIFO 数据内容使用的数据引脚 DO[0:7]均连接到 STM32 同一个 GPIO 端口连续的高 8 位引脚 PB[8:15],这些引脚使用时均配置成输入,程序设计中直接读取 GPIO 端口的高 8 位状态直接获取一个字节的 FIFO 内容,建议在连接这部分数据信号时,参考本设计采用同一个 GPIO 端口连续的 8 位(高 8 位或低 8 位均可),否则会导致读取数据的程序非常复杂。

1.4  XCLK 信号

        本设计中 STM32 的摄像头接口还预留了 PA8 引脚用于与摄像头的 XCLK 连接,STM32的 PA8 可以对外输出时钟信号,所以在使用不带晶振的摄像头时,可以通过该引脚给摄像头提供时钟,秉火摄像头内部已自带晶振,在程序中没有使用 PA8 引脚。

2.  代码设计

2.1  SCCB总线软件实现

2.1.1  宏定义

#ifndef __SCCB_H
#define __SCCB_H#include "stm32f10x.h"/************************** OV7725 连接引脚定义********************************/
#define      OV7725_SIO_C_SCK_APBxClock_FUN              RCC_APB2PeriphClockCmd
#define      OV7725_SIO_C_GPIO_CLK                       RCC_APB2Periph_GPIOC
#define      OV7725_SIO_C_GPIO_PORT                      GPIOC
#define      OV7725_SIO_C_GPIO_PIN                       GPIO_Pin_6#define      OV7725_SIO_D_SCK_APBxClock_FUN              RCC_APB2PeriphClockCmd
#define      OV7725_SIO_D_GPIO_CLK                       RCC_APB2Periph_GPIOC
#define      OV7725_SIO_D_GPIO_PORT                      GPIOC
#define      OV7725_SIO_D_GPIO_PIN                       GPIO_Pin_7#define SCL_H         GPIO_SetBits(OV7725_SIO_C_GPIO_PORT , OV7725_SIO_C_GPIO_PIN) 
#define SCL_L         GPIO_ResetBits(OV7725_SIO_C_GPIO_PORT , OV7725_SIO_C_GPIO_PIN) #define SDA_H         GPIO_SetBits(OV7725_SIO_D_GPIO_PORT , OV7725_SIO_D_GPIO_PIN) 
#define SDA_L         GPIO_ResetBits(OV7725_SIO_D_GPIO_PORT , OV7725_SIO_D_GPIO_PIN) #define SCL_read      GPIO_ReadInputDataBit(OV7725_SIO_C_GPIO_PORT , OV7725_SIO_C_GPIO_PIN) 
#define SDA_read      GPIO_ReadInputDataBit(OV7725_SIO_D_GPIO_PORT , OV7725_SIO_D_GPIO_PIN) #define ADDR_OV7725   0x42void SCCB_GPIO_Config(void);
int SCCB_WriteByte( u16 WriteAddress , u8 SendByte);
int SCCB_ReadByte(u8* pBuffer,   u16 length,   u8 ReadAddress);#endif 

2.1.2  SCCB管脚配置

        前面我们说过,SCCB的引脚配置类似于IIC的引脚配置,这里我们对SCCB的引脚进行初始化,使用的类似软件IIC的协议,可以不用规定必须是IIC的引脚,进行配置为开漏输出模式:

void SCCB_GPIO_Config(void)
{GPIO_InitTypeDef  GPIO_InitStructure; 	/* SCL(PC6)、SDA(PC7)管脚配置 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE );GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;  GPIO_Init(GPIOC, &GPIO_InitStructure);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE );GPIO_InitStructure.GPIO_Pin =GPIO_Pin_7;GPIO_Init(GPIOC, &GPIO_InitStructure);	
}

        按照宏定义进行转换:

void SCCB_GPIO_Config(void)
{GPIO_InitTypeDef  GPIO_InitStructure; /* SCL(PC6)、SDA(PC7)管脚配置 */OV7725_SIO_C_SCK_APBxClock_FUN ( OV7725_SIO_C_GPIO_CLK, ENABLE );GPIO_InitStructure.GPIO_Pin =  OV7725_SIO_C_GPIO_PIN ;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;  GPIO_Init(OV7725_SIO_C_GPIO_PORT, &GPIO_InitStructure);OV7725_SIO_D_SCK_APBxClock_FUN ( OV7725_SIO_D_GPIO_CLK, ENABLE );GPIO_InitStructure.GPIO_Pin =  OV7725_SIO_D_GPIO_PIN ;GPIO_Init(OV7725_SIO_D_GPIO_PORT, &GPIO_InitStructure);}

2.1.3  延时函数

        一个简单的循环等于0时跳出循环,起到延时的作用:

static void SCCB_delay(void)
{	uint16_t i = 400; while(i) { i--; } 
}

2.1.4  SCCB起始信号

        类比IIC协议,起始条件下,SCL高电平期间,SDA从高电平切换到低电平。

static int SCCB_Start(void)
{GPIO_SetBits(GPIOC, GPIO_Pin_7);SCCB_delay();GPIO_SetBits(GPIOC, GPIO_Pin_6);SCCB_delay();GPIO_ResetBits(GPIOC, GPIO_Pin_7);SCCB_delay();GPIO_ResetBits(GPIOC, GPIO_Pin_6);SCCB_delay();}

       为了提高程序的健壮性,可以加入:GPIO_ReadInputDataBit 函数,其作用是读取指定GPIO端口的指定引脚的输入状态,并返回该引脚的输入值(0 或 1) ,进行检测SDA线是否忙碌是否正常。

static int SCCB_Start(void)
{GPIO_SetBits(GPIOC, GPIO_Pin_7);GPIO_SetBits(GPIOC, GPIO_Pin_6);SCCB_delay();if(!GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_7))return DISABLE;	/* SDA线为低电平则总线忙,退出 */GPIO_ResetBits(GPIOC, GPIO_Pin_7);SCCB_delay();if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_7)) return DISABLE;	/* SDA线为高电平则总线出错,退出 */GPIO_ResetBits(GPIOC, GPIO_Pin_7);SCCB_delay();return ENABLE;
}

        按照宏定义进行转换:

static int SCCB_Start(void)
{SDA_H;SCL_H;SCCB_delay();if(!SDA_read)return DISABLE;	/* SDA线为低电平则总线忙,退出 */SDA_L;SCCB_delay();if(SDA_read) return DISABLE;	/* SDA线为高电平则总线出错,退出 */SDA_L;SCCB_delay();return ENABLE;
}

2.1.5  SCCB终止信号

        终止条件下,SCL高电平期间,SDA从低电平切换到高电平。

static void SCCB_Stop(void)
{GPIO_ResetBits(GPIOC, GPIO_Pin_6);SCCB_delay();GPIO_ResetBits(GPIOC, GPIO_Pin_7);SCCB_delay();GPIO_SetBits(GPIOC, GPIO_Pin_6);SCCB_delay();GPIO_SetBits(GPIOC, GPIO_Pin_7);SCCB_delay();
}

        按照宏定义进行转换:

static void SCCB_Stop(void)
{SCL_L;SCCB_delay();SDA_L;SCCB_delay();SCL_H;SCCB_delay();SDA_H;SCCB_delay();
}

2.1.6  SCCB应答信号

        与 I2C 时序类似,在 SCCB 时序也使用自由位(Don’t care bit )和非应答(NA)信号来保证正常通讯。自由位和非应答信号位于 SCCB 每个传输阶段中的第九位。

        在写数据的第一个传输阶段中,第 9 位为自由位,在一般的正常通讯中,第 9 位时,主机的 SDA 线输出高电平,而从机把 SDA 线拉低作为响应,只是传输的内容分别为目的寄存器地址和要写入的数据。

        应答信号的发送是 SCCB 协议中的一个重要步骤,用于确认数据传输的成功。

static void SCCB_Ack(void)
{GPIO_ResetBits(GPIOC, GPIO_Pin_6);SCCB_delay();GPIO_ResetBits(GPIOC, GPIO_Pin_7);SCCB_delay();GPIO_SetBits(GPIOC, GPIO_Pin_6);SCCB_delay();GPIO_ResetBits(GPIOC, GPIO_Pin_6);SCCB_delay();
}

        按照宏定义进行转换:

static void SCCB_Ack(void)
{	SCL_L;SCCB_delay();SDA_L;SCCB_delay();SCL_H;SCCB_delay();SCL_L;SCCB_delay();
}

2.1.7  SCCB非应答信号

        非应答信号的发送也是 SCCB 协议中的一部分,用于处理数据传输失败或其他错误情况。在某些情况下,如果从设备无法正确接收数据,主设备可能会发送非应答信号并采取相应的错误处理措施。

static void SCCB_NoAck(void)
{GPIO_ResetBits(GPIOC, GPIO_Pin_6);SCCB_delay();GPIO_SetBits(GPIOC, GPIO_Pin_7);SCCB_delay();GPIO_SetBits(GPIOC, GPIO_Pin_6);SCCB_delay();GPIO_ResetBits(GPIOC, GPIO_Pin_6);SCCB_delay();
}

        按照宏定义进行转换:

static void SCCB_NoAck(void)
{	SCL_L;SCCB_delay();SDA_H;SCCB_delay();SCL_H;SCCB_delay();SCL_L;SCCB_delay();
}

2.1.8  SCCB等待应答信号

        让主机把 SDA 线设为高电平,延时一段时间后再检测 SDA 线的电平,若为低则返回 ENABLE 表示接收到从机的应答,反之返回 DISABLE。(L代表低,H代表高,以下直接使用SCL和SDA的宏定义表示)

static int SCCB_WaitAck(void) 	
{SCL_L;SCCB_delay();SDA_H;			SCCB_delay();SCL_H;SCCB_delay();if(SDA_read){SCL_L;return DISABLE;}SCL_L;return ENABLE;
}

2.1.9  发送数据

        首先,我们先创建一个用于接收数据的参数SendByt,它接受一个 8 位的字节数据作为输入参数,使用一个循环逐位发送这个字节的数据。循环从最高位开始,依次发送每一位,直到最低位。在每一次循环中,首先将 SCL(时钟线)拉低,然后通过 SCCB_delay 函数产生一定延迟,接着,根据 SendByte 的当前最高位,控制 SDA(数据线)为高电平或低电平,以此来发送数据的当前位,然后将 SendByte 左移一位,准备发送下一位数据。通过循环8次来完成一位数据的发送。

static void SCCB_SendByte(uint8_t SendByte) 
{uint8_t i=8;while(i--){SCL_L;SCCB_delay();if(SendByte&0x80)SDA_H;  else SDA_L;   SendByte<<=1;SCCB_delay();SCL_H;SCCB_delay();}SCL_L;
}

2.1.10  SCCB总线返回的数据

        首先声明了一个变量 i 并初始化为 8,以及再声明了一个变量 ReceiveByte 并初始化为 0,用于存储接收到的字节数据,然后,将 SDA(数据线)拉高,准备接收数据,通过一个循环逐位接收一个字节的数据。循环从最高位开始,依次接收每一位,直到最低位,读取 SDA 线上的数据,并根据其值决定是否将 ReceiveByte 的当前最低位设置为 1,将 ReceiveByte 左移一位,准备接收下一位数据。

static int SCCB_ReceiveByte(void)  
{ uint8_t i=8;uint8_t ReceiveByte=0;SDA_H;				while(i--){ReceiveByte<<=1;      SCL_L;SCCB_delay();SCL_H;SCCB_delay();	if(SDA_read){ReceiveByte|=0x01;}}SCL_L;return ReceiveByte;
}

2.1.11  SCCB写一个字节数据

        首先,明确两个宏,其实OV7725的设备地址:

#define ADDR_OV7725 0x42
#define DEV_ADR ADDR_OV7725

        为了确保SCCB总线通信正常启动,我们可以先进行判断SCCB是否发送起始信号,若是发送继续,若是失败则返回DISABLE。

    if(!SCCB_Start()){return DISABLE;}

        然后,通过 SCCB_SendByte 函数发送设备地址 DEV_ADR,用于指定要通信的设备,此时指定要通信的设备会发送应答,通过判断本机时候接收到应答,来确定两个设备间是否能进行正常通信,若是不能则终止信号,并返回DISABLE。

    SCCB_SendByte( DEV_ADR );                   if( !SCCB_WaitAck() ){SCCB_Stop(); return DISABLE;}

        若是能则将要写入的寄存器地址的低八位(WriteAddress 的低八位)发送给设备,以确定写入数据的目标寄存器,再次等待指定要通信的设备的应答,然后发送要写入的数据 SendByte 给设备,再次等待设备的应答,,停止 SCCB 通信,并返回 ENABLE 表示写入操作成功。

    SCCB_SendByte((uint8_t)(WriteAddress & 0x00FF));  SCCB_SendByte(SendByte);SCCB_WaitAck();   SCCB_Stop(); return ENABLE;

完整代码:

#define ADDR_OV7725 0x42
#define DEV_ADR ADDR_OV7725int SCCB_WriteByte( uint16_t WriteAddress , uint8_t SendByte )
{		if(!SCCB_Start()){return DISABLE;}SCCB_SendByte( DEV_ADR );                    /* Æ÷¼þµØÖ· */if( !SCCB_WaitAck() ){SCCB_Stop(); return DISABLE;}SCCB_SendByte((uint8_t)(WriteAddress & 0x00FF));   /* ÉèÖõÍÆðʼµØÖ· */      SCCB_WaitAck();	SCCB_SendByte(SendByte);SCCB_WaitAck();   SCCB_Stop(); return ENABLE;
}

2.1.12  SCCB读一串数据

int SCCB_ReadByte(uint8_t* pBuffer, uint16_t length, uint8_t ReadAddress)
{	if(!SCCB_Start()){return DISABLE;}SCCB_SendByte( DEV_ADR );         /* Æ÷¼þµØÖ· */if( !SCCB_WaitAck() ){SCCB_Stop(); return DISABLE;}SCCB_SendByte( ReadAddress );     /* ÉèÖõÍÆðʼµØÖ· */      SCCB_WaitAck();	SCCB_Stop(); if(!SCCB_Start()){return DISABLE;}SCCB_SendByte( DEV_ADR + 1 );     /* Æ÷¼þµØÖ· */ if(!SCCB_WaitAck()){SCCB_Stop(); return DISABLE;}while(length){*pBuffer = SCCB_ReceiveByte();if(length == 1){SCCB_NoAck();}else{SCCB_Ack(); }pBuffer++;length--;}SCCB_Stop();return ENABLE;
}

OV7725摄像头_时光の尘的博客-CSDN博客

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

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

相关文章

上位机图像处理和嵌入式模块部署(f103 mcu运行freertos)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 mcu一般有两个用途,一个是控制,一个是非控制。控制类的应用一般要求实时性比较高,什么时候做什么,都是有严格的时间要求的。而非控制类的应用,则要求实现尽可能多的功能,比如…

spring boot整合j2cache 配置项目全局键标识 帮助定位是哪个项目产生的缓存

我们利用 j2cache 存进 redis的缓存 key 可以加个全局标识 这样 到时看缓存 方便别人看是哪个项目存进去的 例如 这里 我们存入的 book 我们 keys * 查看 就知道是个book 但不知道具体来自那套系统 我们在 j2cache.properties 中加上 redis.namespace 项目全局键标识 我们…

42-5 应急响应之日志分析

一、Windows 系统日志排查 1)日志概述 在 Windows 2000 专业版、Windows XP 和 Windows Server 2003 中: 系统日志的位置为 C:\WINDOWS\System32\config\SysEvent.evt安全性日志的位置为 C:\WINDOWS\System32\config\SecEvent.evt应用程序日志的位置为 C:\WINNT\System32\c…

【漏洞复现】海康威视综合安防管理平台 iSecure Center applyCT fastjson 远程代码执行

0x01 漏洞名称 海康威视综合安防管理平台 iSecure Center applyCT fastjson 远程代码执行 0x02 漏洞影响 0x03 搜索引擎 app"HIKVISION-综合安防管理平台"0x04 漏洞详情 POST /bic/ssoService/v1/applyCT HTTP/1.1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Wi…

NASA数据集——阿尔法喷气式大气实验二氧化碳和甲烷数据

Alpha Jet Atmospheric eXperiment Carbon Dioxide and Methane Data 阿尔法喷气式大气实验二氧化碳和甲烷数据 简介 Alpha Jet Atmospheric eXperiment (AJAX) 是美国国家航空航天局艾姆斯研究中心与 H211, L.L.C. 公司的合作项目&#xff0c;旨在促进对加利福尼亚、内华达…

vue+iview tabs context-menu 弹出框怎么修改样式

今天遇到一个需求说页面顶部的菜单右键弹出框离得有点远 代码是这样 <Tabs type"card" closable class"main-tags-col-tabs" v-model"activeTab" on-click"handleClickTag" :before-remove"handleBeforeRemove" capt…

什么是容器:从基础到进阶的全面介绍

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

【Linux 网络】网络基础(三)(网络层协议:IP 协议)

在复杂的网络环境中确定一个合适的路径。 一、TCP 与 IP 的关系 IP 层的核心作用是定位主机&#xff0c;具有将数据从主机 A 发送到主机 B 的能力&#xff0c;但是能力并不能保证一定能够做到&#xff0c;所以这时就需要 TCP 起作用了&#xff0c;TCP 可以通过超时重传、拥塞控…

【必备工具】gitee上传-保姆级教程

目录 1.gitee是什么 2.gitee怎么注册 ​编辑 3.gitee怎么提交代码 4.gitee的三板斧 Clone仓库 Q&A 1. Gitee 只有三板斧吗&#xff1f; 2. Git 教了&#xff0c;Gitee 上没有绿点怎么办&#xff1f; 3. 用户名和密码输入错误怎么办&#xff1f; 4. 操作时不小心…

【c++基础】和谐分组

题目描述 s 班共有 n 名学生&#xff0c;按照学号从 1 到的顺序每名学生的身高分别为 a[1],a[2]...a[n]。由于是新学期&#xff0c;s 班需要进行分组&#xff0c;分组的要求如下&#xff1a; 进行分组的组数不能超过 k。 每组的人的学号必须相邻。 由于身高差过大的人分在同一…

wordpress主题给网站增加一个版权声明区块代码分享

在数字化时代&#xff0c;网络上的信息传播变得越来越便捷&#xff0c;给人们生活和工作带来了极大的便利。然而&#xff0c;在这个过程中也产生了很多版权问题。为了更好地保护自己的版权&#xff0c;许多网站开始在其网页上添加版权声明。本文将探讨在网站上添加版权声明的重…

机器人运动轨迹学习——GMM/GMR算法

机器人运动轨迹学习——GMM/GMR算法 前置知识 GMM的英文全称为&#xff1a;Gaussian mixture model&#xff0c;即高斯混合模型&#xff0c;也就是说&#xff0c;它是由多个高斯模型进行混合的结果&#xff1a;当然&#xff0c;这里的混合是带有权重概念的。 一维高斯分布 GMM中…

win11安装MySQL

目录[-] 1. 1. 下载2. 2. 安装 参考文档&#xff1a;MySQL :: MySQL 8.4 Reference Manual 1. 下载 mysql官网下载msi安装程序&#xff1a;MySQL :: Begin Your Download 2. 安装 运行下载的mis程序,逐步安装。 安装模式&#xff1a; complete; 进入配置&#xff1a; data di…

Spring Boot 项目统一异常处理

在 Spring Boot 项目开发中&#xff0c;异常处理是一个非常重要的环节。良好的异常处理不仅能提高应用的健壮性&#xff0c;还能提升用户体验。本文将介绍如何在 Spring Boot 项目中实现统一异常处理。 统一异常处理有以下几个优点&#xff1a; 提高代码可维护性&#xff1a;…

Linux内核重置root密码

Ubuntu 首先重新启动Ubuntu系统&#xff0c;然后快速按下shift键&#xff0c;以调出grub启动菜单在这里我们选择第二个&#xff08;Ubuntu高级选项&#xff09;&#xff0c;选中后按下Enter键 选择最高的Linux内核版本所对应的recovery mode模式&#xff0c;按e键编辑启动项 在…

mac brew 命令详解

brew 是 macOS 系统中 Homebrew 的命令行工具&#xff0c;用于在 macOS 上安装、更新和管理各种软件包。以下是对 brew 命令的详细介绍&#xff0c;按照功能和使用频率进行分点和归纳&#xff1a; 1. 安装和卸载软件包 安装软件包&#xff1a;使用 install 命令&#xff0c;后…

测试用例篇

测试用例的基本要素 **测试用例是为了实施测试而向被测试的系统提供的一组集合&#xff0c;这组集合包含&#xff1a;测试环 **境、操作步骤、测试数据、预期结果等要素.评价测试用例的标准&#xff1a;**对比好坏用例的评价标准 **用例表达清楚&#xff0c;无二义性用例可操作…

Spring服务启动后就执行某个方法

下边按照执行顺序前后&#xff0c;测试代码结果截图放到最后&#xff1a; 1、注解PostConstruct 时间&#xff1a;当前bean被创建并且所有的依赖注入完成之后执行&#xff1b; 使用&#xff1a;当前bean 所在类内的某个方法上 添加该注解&#xff1b;该方法没有参数&#xf…

探索移动云服务:构建高效移动互联网应用的最佳实践

一、移动云服务简介 官网&#xff1a;https://ecloud.10086.cn 移动云&#xff0c;或称为移动云计算&#xff0c;是通过无线网络向移动设备用户提供云计算服务的技术。它使用户能够通过智能手机、平板电脑和笔记本电脑等各类移动设备&#xff0c;在任何时间、任何地点便捷地访…