搜索
bottom↓
回复: 121

STM32的IAP方案

  [复制链接]

出0入0汤圆

发表于 2011-12-10 01:08:33 | 显示全部楼层 |阅读模式
几乎所有的同类书籍都介绍综合性的应用示例如“万年历 + 温度显示 + 闹钟响铃 + 计时表”这样的一个实时时钟范例或“STM32 + 音频解码 + 大容量存储方案”这样的MP3播放器范例。这些综合性实例的目的在于引领读者进行综合性实验,达到把单片机的基础模块整合运用的目的。这些实例普遍存在一种共同点,即“练手”意义要大于“实用”的意义。本文将讲述一个STM32的综合性应用示例,该示例将涉及到STM32微控制器的时钟系统、GPIO、定时器、中断系统、异步串口以及内置可编程flash等设备的应用,作为一个综合性实验的同时还具有很强的“实用”意义。这个示例就是STM32的IAP方案。

         IAP,全称是“In-Application

Programming”,中文解释为“在程序中编程”。IAP是一种对通过微控制器的对外接口(如USART,IIC,CAN,USB,以太网接口甚至是无线射频通道)对正在运行程序的微控制器进行内部程序的更新的技术(注意这完全有别于ICP或者ISP技术)。ICP(In-Circuit Programming)技术即通过在线仿真器对单片机进行程序烧写,而ISP技术则是通过单片机内置的bootloader程序引导的烧写技术。无论是ICP技术还是ISP技术,都需要有机械性的操作如连接下载线,设置跳线帽等。若产品的电路板已经层层密封在外壳中,要对其进行程序更新无疑困难重重,若产品安装于狭窄空间等难以触及的地方,更是一场灾难。但若进引入了IAP技术,则完全可以避免上述尴尬情况,而且若使用远距离或无线的数据传输方案,甚至可以实现远程编程和无线编程。这绝对是ICP或ISP技术无法做到的。某种微控制器支持IAP技术的首要前提是其必须是基于可重复编程闪存的微控制器。STM32微控制器带有可编程的内置闪存,同时STM32拥有在数量上和种类上都非常丰富的外设通信接口,因此在STM32上实现IAP技术是完全可行的。

         实现IAP技术的核心是一段预先烧写在单片机内部的IAP程序。这段程序主要负责与外部的上位机软件进行握手同步,然后将通过外设通信接口将来自于上位机软件的程序数据接收后写入单片机内部指定的闪存区域,然后再跳转执行新写入的程序,最终就达到了程序更新的目的。

在STM32微控制器上实现IAP程序之前首先要回顾一下STM32的内部闪存组织架构和其启动过程。STM32的内部闪存地址起始于0x8000000,一般情况下,程序文件就从此地址开始写入。此外STM32是基于Cortex-M3内核的微控制器,其内部通过一张“中断向量表”来响应中断,程序启动后,将首先从“中断向量表”取出复位中断向量执行复位中断程序完成启动。而这张“中断向量表”的起始地址是0x8000004,当中断来临,STM32的内部硬件机制亦会自动将PC指针定位到“中断向量表”处,并根据中断源取出对应的中断向量执行中断服务程序。最后还需要知道关键的一点,通过修改STM32工程的链接脚本可以修改程序文件写入闪存的起始地址。

在STM32微控制器上实现IAP方案,除了常规的串口接收数据以及闪存数据写入等常规操作外,还需注意STM32的启动过程和中断响应方式。图1显示了STM32常规的运行流程。



(原文件名:1.jpg)  

图1

对图1解读如下:

1、        STM32复位后,会从地址为0x8000004处取出复位中断向量的地址,并跳转执行复位中断服务程序,如图1中标号○1所示。

2、        复位中断服务程序执行的最终结果是跳转至C程序的main函数,如图1中标号○2所示,而main函数应该是一个死循环,是一个永不返回的函数。

3、        在main函数执行的过程中,发生了一个中断请求,此时STM32的硬件机制会将PC指针强制指回中断向量表处,如图1中标号○3所示。

4、        根据中断源进入相应的中断服务程序,如图1中标号○5所示。

5、        中断服务程序执行完毕后,程序再度返回至main函数中执行,如图1中标号○6所示。

若在STM32中加入了IAP程序,则情况会如图2所示。



(原文件名:2.jpg)   

图2

对图2的解读如下:

1、        STM32复位后,从地址为0x8000004处取出复位中断向量的地址,并跳转执行复位中断服务程序,随后跳转至IAP程序的main函数,如图2中标号○1、○2所示。这个过程和图1相应部分是一致的。

2、        执行完IAP过程后(STM32内部多出了新写入的程序,图2中以灰色底纹方格表示,地址始于0x8000004+N+M)跳转至新写入程序的复位向量表,取出新程序的复位中断向量的地址,并跳转执行新程序的复位中断服务程序,随后跳转至新程序的main函数,其过程如图2的标号○3所示。新程序的main函数应该也具有永不返回的特性。同时应该注意在STM32的内部存储空间在不同的位置上出现了2个中断向量表。

3、        在新程序main函数执行的过程中,一个中断请求来临,PC指针仍会回转至地址为0x8000004中断向量表处,而并不是新程序的中断向量表,如图2中标号○5所示。注意到这是由STM32的硬件机制决定的。

4、        根据中断源跳转至对应的中断服务,如图2中标号○6所示。注意此时是跳转至了新程序的中断服务程序中。

5、        中断服务执行完毕后,返回main函数。如图2中标号○8所示。

从上述两个过程的分析可以得知,对将使用IAP过程写入的程序要满足2个要求:

1、新程序必须从IAP程序之后的某个偏移量为x的地址开始;

2、必须将新程序的中断向量表相应的移动,移动的偏移量为x;

而设置程序起始位置的方法是(keil uvision4集成开发环境)在工程的“Option for Target….”界面中的“Target”页里将“IROM”的“Start”列改为欲使程序起始的地方,如图3中将程序起始位置设为0x8002000。



(原文件名:3.jpg)  

图3

将中断向量表移动的方法是在程序中加入函数:

void NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset);

其中参数NVIC_VectTab为中断向量表起始位置,而参数Offset则为地址偏移量,如将中断向量表移至0x8002000处,则应调用该函数如下:

void NVIC_SetVectorTable(0x8000000, 0x2000);

同时有必要提醒读者注意的是,此函数只会修改STM32程序中用于存储中断向量的结构体变量,而不会实质地改变中断向量表在闪存中的物理位置,详情请研究该程序原型。

有了以上准备后就可以着手设计一个IAP方案了,如下:

1、STM32复位后,利用一个按键的状态进行同步,当按键按下时表示将要进行IAP过程;

2、IAP过程中,通过上位机软件向STM32的USART1设备发送所要更新的程序文件,STM32接收到数据后转而从0x8002000地址开始写入收到的数据;

3、STM32借助定时器来判断数据是否完全接收,完全接收后IAP过程结束;

4、再次复位后,跳转0x8002004地址开始运行新写入的程序;

最后提出几点注意事项:

1、具体实现的工程见附件;

2、利用IAP写入的程序文件最好是.bin格式的文件,但不能是.hex格式的文件;

3、向STM32发送程序文件时尽量慢一些,因为STM32对FLASH的写入速度往往跟不上通讯外设接口的速度;

4、建议在STM32和上位机之间设计一套握手机制和出错管理机制,这样可以大幅提高IAP的成功率;

5、附件中的IAP工程具体运行现象为,按着连接于GPIOA.0引脚上的按键后对STM32进行复位操作,若连接于GPIOA.4引脚上的LED被点亮则表示进入了IAP程序,等待从USART1接口传入欲更新的程序文件。程序文件更新完毕后,LED被熄灭。此时再度对STM32进行复位,就开始运行新写入的程序了。

出0入0汤圆

发表于 2011-12-10 05:35:17 | 显示全部楼层
mark

出0入4汤圆

发表于 2011-12-10 05:59:07 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-10 09:08:13 | 显示全部楼层
好东西踩个脚印

出0入0汤圆

发表于 2011-12-10 09:09:39 | 显示全部楼层
mark!!!

出0入0汤圆

发表于 2011-12-10 09:41:06 | 显示全部楼层
还是要按键触发

出0入0汤圆

发表于 2011-12-10 09:42:22 | 显示全部楼层
Mark

出0入0汤圆

发表于 2011-12-10 09:52:54 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-3-2 00:22:02 | 显示全部楼层
mark

出200入0汤圆

发表于 2012-3-2 10:29:06 | 显示全部楼层
这个不错

出0入0汤圆

发表于 2012-4-9 11:39:20 | 显示全部楼层
讲的相当的到位

出0入0汤圆

发表于 2012-6-3 10:37:47 | 显示全部楼层
请问大侠,是用什么软件传送BIN格式文件的呢?哪里可以下到啊?

出0入0汤圆

发表于 2012-6-3 11:40:58 | 显示全部楼层
本帖最后由 NG_Account 于 2012-6-3 11:44 编辑

按键触发只是一种方式而已,软件协议触发也可以。只要有既定的协议,触发IAP方式有很多。
我之前实现的是电脑通过TCP将加密过的升级文件发送给一个ARM9处理器,ARM9处理器再用485分包发送给需要升级的多台终端设备,设备收到文件先暂存flash非应用程序区,接收完成再进行解密。重启,更新应用程序区。

出0入0汤圆

发表于 2012-8-21 00:07:29 | 显示全部楼层
收集一下iap帖子。

出0入0汤圆

发表于 2012-8-21 17:23:21 | 显示全部楼层
Mark!      

出0入0汤圆

发表于 2013-5-7 14:23:21 | 显示全部楼层
STM32 IAP

出0入0汤圆

发表于 2013-5-11 22:45:59 | 显示全部楼层
楼主我想问下,1:在图解2的第二步,运行完IAP程序后,是如何指向新的中断向量表的?2:下次上电后就开始运行新的程序了?为什么

出20入118汤圆

发表于 2013-5-11 23:15:57 | 显示全部楼层
mark   iap 作用是蛮大的

出0入0汤圆

发表于 2013-7-26 15:15:27 | 显示全部楼层
好东西,颇有收获。

出0入0汤圆

发表于 2013-7-26 15:16:53 | 显示全部楼层
mark       正需要

出0入0汤圆

发表于 2013-7-27 12:31:55 | 显示全部楼层
我单位要求所有IAP都必须代码最小化,而且传输加密化(串行口上不得截获真实代码)。我们都是在C8051Fxxx系列0.5KB,STM32Fxxx系列4KB内完成。之所以4KB是因为STM32一个写保护位就保护4KB区域,所以IAP再小也没啥意义了。

出0入0汤圆

发表于 2013-8-11 13:52:23 来自手机 | 显示全部楼层
mark……
顶一个…

出0入0汤圆

发表于 2013-8-25 20:52:29 | 显示全部楼层
mark!!!!!!!!!!!!!!!

出0入8汤圆

发表于 2013-8-25 22:54:31 | 显示全部楼层
mark,正在做STM32的IAP,正需要,谢谢!

出0入0汤圆

发表于 2013-8-26 08:34:29 | 显示全部楼层
留个脚印
头像被屏蔽

出0入0汤圆

发表于 2013-8-26 11:16:46 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2013-8-30 15:12:43 | 显示全部楼层
好东西 谢谢 收藏

出0入0汤圆

发表于 2013-9-10 00:52:45 | 显示全部楼层
fastweb 发表于 2013-7-27 12:31
我单位要求所有IAP都必须代码最小化,而且传输加密化(串行口上不得截获真实代码)。我们都是在C8051Fxxx系 ...

你好,朋友。请教下,新代码一定要通过串口之类进行传输么?
能不能用usb,SD等flash存储器呢?谢谢。

出0入0汤圆

发表于 2013-9-10 10:38:43 | 显示全部楼层
youpeng 发表于 2013-9-10 00:52
你好,朋友。请教下,新代码一定要通过串口之类进行传输么?
能不能用usb,SD等flash存储器呢?谢谢。 ...

毫无疑问,既然是自己写的IAP代码,什么方法都可以,只要你有相应的接口(USB,SDCARD....)。只不过IAP代码量会多一点,留给主程序的代码区会小一点。

出0入0汤圆

发表于 2013-9-16 16:00:11 | 显示全部楼层
多谢楼主,正需要

出0入0汤圆

发表于 2013-10-16 17:33:03 | 显示全部楼层
太需要了,谢谢

出0入0汤圆

发表于 2013-10-21 14:56:47 | 显示全部楼层
正在做一个项目,要用到GPRS远程升级,谢谢了

出0入0汤圆

发表于 2013-10-29 11:39:11 | 显示全部楼层
不错,很有参考意义!

出0入0汤圆

发表于 2013-11-4 11:14:26 | 显示全部楼层
独清行者 发表于 2012-6-3 10:37
请问大侠,是用什么软件传送BIN格式文件的呢?哪里可以下到啊?

我也灰常纠结这个问题啊    难不成还自己写个呀

出0入0汤圆

发表于 2013-11-4 11:14:55 | 显示全部楼层
FASHAOYIHAOAMO 发表于 2013-11-4 11:14
我也灰常纠结这个问题啊    难不成还自己写个呀

期待工具啊

出0入0汤圆

发表于 2013-11-4 14:54:15 | 显示全部楼层
不错不错

出0入0汤圆

发表于 2013-11-26 08:37:50 | 显示全部楼层
mark            

出0入0汤圆

发表于 2013-11-26 22:16:50 | 显示全部楼层
写的很好,学习

出0入0汤圆

发表于 2013-11-26 23:24:23 | 显示全部楼层
make 学习

出0入0汤圆

发表于 2013-11-28 17:40:35 | 显示全部楼层
mark  mark

出0入0汤圆

发表于 2013-11-29 17:42:37 | 显示全部楼层
参考这个帖子,总算也实现了iap

出0入0汤圆

发表于 2013-12-2 09:36:18 | 显示全部楼层
MARK                                             

出0入0汤圆

发表于 2013-12-3 13:45:39 | 显示全部楼层
已经有自己的iap了, 顶

出0入0汤圆

发表于 2013-12-5 14:03:26 | 显示全部楼层
不是太懂,谁有示例工程参考一下

出0入0汤圆

发表于 2013-12-5 14:17:36 来自手机 | 显示全部楼层
学习了,不错啊

出0入0汤圆

发表于 2013-12-5 14:21:32 | 显示全部楼层
mark+mark 支持

出0入0汤圆

发表于 2013-12-5 14:58:33 | 显示全部楼层
IAP自己的中断程序跑哪里?

出0入0汤圆

发表于 2013-12-25 22:28:52 | 显示全部楼层
Mark 加油

出0入0汤圆

发表于 2013-12-26 09:37:35 | 显示全部楼层
不知道如何实现多种iap于一身?

出0入0汤圆

发表于 2013-12-26 12:40:02 | 显示全部楼层
#在这里快速回复#谢谢分享

出0入0汤圆

发表于 2013-12-26 13:09:24 | 显示全部楼层
学习一下,STM32IAP,顶

出0入0汤圆

发表于 2013-12-26 15:29:44 | 显示全部楼层
谢谢分享。

出0入0汤圆

发表于 2013-12-26 17:10:49 | 显示全部楼层
fastweb 发表于 2013-9-10 10:38
毫无疑问,既然是自己写的IAP代码,什么方法都可以,只要你有相应的接口(USB,SDCARD....)。只不过IAP ...

针对无线模块的升级怎么做啊?

出0入0汤圆

发表于 2013-12-29 08:52:34 | 显示全部楼层
顶,正好需要这个。。。

出0入0汤圆

发表于 2013-12-29 09:32:50 | 显示全部楼层
FASHAOYIHAOAMO 发表于 2013-11-4 11:14
我也灰常纠结这个问题啊    难不成还自己写个呀

自定义协议灵活性大
写个匹配的上位机不是难事

出0入0汤圆

发表于 2013-12-29 09:34:01 | 显示全部楼层
zxc2769 发表于 2013-12-26 17:10
针对无线模块的升级怎么做啊?

无线模块只是一个通讯接口
只不过多个无线接口协议拔了
和串口没啥区别
只是数据传输通道变了

出0入0汤圆

发表于 2013-12-29 12:19:51 | 显示全部楼层
mark......

出0入0汤圆

发表于 2013-12-29 12:35:17 | 显示全部楼层
好东西,收藏抽空研究一下

出0入0汤圆

发表于 2013-12-29 21:42:13 | 显示全部楼层
先收藏了

出0入0汤圆

发表于 2013-12-30 20:49:46 | 显示全部楼层
讲的很好,这个是有用的。

出0入0汤圆

发表于 2013-12-31 11:43:25 | 显示全部楼层
好东西,谢谢你的分享

出0入0汤圆

发表于 2014-1-4 23:48:52 | 显示全部楼层
mark                                                                                       !

出0入0汤圆

发表于 2014-1-4 23:49:08 | 显示全部楼层
mark。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

出0入0汤圆

发表于 2014-1-8 11:38:06 | 显示全部楼层
设置IROM需要注意,那IRAM的地址呢?

出0入0汤圆

发表于 2014-1-8 11:40:33 | 显示全部楼层
付新辉 发表于 2014-1-8 11:38
设置IROM需要注意,那IRAM的地址呢?

Bootloader跳轉後,如果不再執行Bootloader的程序,其實所有的IRAM都可以給App使用,不用分二段

出0入0汤圆

发表于 2014-1-21 10:57:27 | 显示全部楼层
现在正在用485写IAP程序,学习了!

出0入0汤圆

发表于 2014-3-4 11:40:19 | 显示全部楼层
mark!!!!!!!!

出0入0汤圆

发表于 2014-3-9 22:25:37 | 显示全部楼层
好东西,留下脚印

出0入0汤圆

发表于 2014-3-10 22:04:08 | 显示全部楼层
留个脚印,马上就用得着

出0入0汤圆

发表于 2014-4-4 12:50:46 | 显示全部楼层
mark                                

出0入0汤圆

发表于 2014-4-12 23:00:32 | 显示全部楼层
正在做STM32的IAP,正需要,谢谢!
等我有心得了一定跟帖

出0入0汤圆

发表于 2014-4-12 23:09:28 | 显示全部楼层
记录备用

出0入0汤圆

发表于 2014-5-30 16:26:55 | 显示全部楼层
非常非常好

出0入0汤圆

发表于 2014-6-30 10:25:24 | 显示全部楼层
好东西,多谢分享。。

出0入0汤圆

发表于 2014-6-30 10:34:41 | 显示全部楼层
马瑞卡            

出0入0汤圆

发表于 2014-7-14 14:58:27 | 显示全部楼层
好东西,支持一下

出0入0汤圆

发表于 2014-7-14 17:57:46 来自手机 | 显示全部楼层
mark,好。留名,以后有用

出0入0汤圆

发表于 2014-7-17 11:17:20 | 显示全部楼层
学习学习~~~~

出0入0汤圆

发表于 2014-7-29 11:14:56 | 显示全部楼层
IAP里的中断在哪里运行呢????

出0入0汤圆

发表于 2014-8-10 13:04:22 | 显示全部楼层
chenweigang 发表于 2013-5-11 22:45
楼主我想问下,1:在图解2的第二步,运行完IAP程序后,是如何指向新的中断向量表的?2:下次上电后就开始运 ...

写得很好。
同问。

出0入0汤圆

发表于 2014-8-11 16:41:15 | 显示全部楼层
好东西,正准备做IAP呢,有用得着

出0入0汤圆

发表于 2014-8-19 09:21:53 | 显示全部楼层
ap000102 发表于 2014-8-11 16:41
好东西,正准备做IAP呢,有用得着

IAP弄得咋样了? 有空一起讨论哦  我的QQ:1012015251

出0入0汤圆

发表于 2014-8-19 15:25:20 | 显示全部楼层
楼主你好 ,一段代码实在不理解 啊  求解释?
void TIMER_TimerStart(u8 TimerIdent, u32 TimeOut, void (*Timeoutfuc)(void* parameter), void* parameter, u8 flag)
{
        if(TimerIdent > 9)
        {
                return;
        }
       
        __disable_irq();
       
        TimerList[TimerIdent].Timeoutcnt = TimeOut;
        TimerList[TimerIdent].Timeout = TimeOut;
        TimerList[TimerIdent].Timeoutfuc = Timeoutfuc;  
        TimerList[TimerIdent].Parameter = parameter;
        TimerList[TimerIdent].Timerflag = flag;
       
        __enable_irq();
}


void TIMER_Execute(void)
{
        u8 i = 0;                                                                                                                       
        for(i = 0; i < 10; i++)                                                                                               
        {
                if((TimerList[i].Timeoutcnt != 0) && (TimerList[i].Timeoutcnt <= 1000000))
                {
                        TimerList[i].Timeoutcnt--;                                                                               
                        if(TimerList[i].Timeoutcnt == 0)                                                               
                        {
                                if(TimerList[i].Timerflag != TIMER_PERIOD)                               
                                {
                                        TimerList[i].Timeoutcnt = 1000001;                                               
                                }
                                else
                                {
                                        TimerList[i].Timeoutcnt = TimerList[i].Timeout;                       
                                }
                                TimerList[i].Timeoutfuc(TimerList[i].Parameter);                               
                        }
                }
        }
}

出0入0汤圆

发表于 2014-8-19 15:26:57 | 显示全部楼层
  1. #define MAXBUFFER        512
  2. #define IAPSTART        0x8002000
  3. #define PAGESIZE        1024

  4. #define TIMER_ONESHOT                0
  5. #define TIMER_PERIOD                1

  6. typedef struct __TIMER
  7. {
  8.         u32 Timeoutcnt;
  9.         u32 Timeout;
  10.         void (*Timeoutfuc)(void* parameter);
  11.         void* Parameter;
  12.         u8 Timerflag;
  13. }Timer_typedef;

  14. static Timer_typedef TimerList[10];

  15. static u8 UsartBuffer[MAXBUFFER];
  16. static volatile u16 UsartWptr = 0;
  17. static u16 UsartRptr = 0;
  18. static u8 Timeout = 0;
  19. typedef  void (*pFunction)(void);
  20. pFunction Jump_To_Application;
复制代码

出0入0汤圆

发表于 2014-8-25 08:38:19 | 显示全部楼层
说得好,很是需要。

出0入0汤圆

发表于 2014-9-9 08:18:59 | 显示全部楼层
顶一个  mARK

出0入0汤圆

发表于 2014-9-9 10:20:22 | 显示全部楼层
好教程,希望我也可以学会

出0入0汤圆

发表于 2014-9-9 11:18:08 | 显示全部楼层
没有利用USB 盘iap的吗在坛子里看到一个,需要增加硬件成本............

出0入0汤圆

发表于 2014-9-9 12:00:18 | 显示全部楼层
学习了,应该就是划分一个bootloader区,通过bootloader连接外部接口更新程序。

出0入0汤圆

发表于 2014-9-17 11:10:25 | 显示全部楼层
学习下。

出0入0汤圆

发表于 2014-9-17 11:17:29 | 显示全部楼层

谢谢分享。。。。。。

出0入0汤圆

发表于 2014-9-17 11:29:35 | 显示全部楼层
mark先     

出0入0汤圆

发表于 2014-9-17 13:36:23 | 显示全部楼层
IAP貌似就是串口下载啊??

出0入4汤圆

发表于 2014-9-20 09:40:44 | 显示全部楼层
不错,正需要

出0入0汤圆

发表于 2014-9-27 10:41:24 | 显示全部楼层
学习了~

出0入0汤圆

发表于 2014-9-28 11:07:06 | 显示全部楼层
附件呢,有工程就好了

出0入0汤圆

发表于 2014-9-28 11:44:55 | 显示全部楼层
guyong2012 发表于 2014-9-17 13:36
IAP貌似就是串口下载啊??

那是物理层,应用层就是在重新开辟一段程序段,让程序计数器从该程序段开始执行程序,并改变了中断向量表

出0入0汤圆

发表于 2014-9-28 11:46:18 | 显示全部楼层
磊磊映画 发表于 2014-9-28 11:44
那是物理层,应用层就是在重新开辟一段程序段,让程序计数器从该程序段开始执行程序,并改变了中断向量表 ...

IAP的物理层可以是串口 IIC SPI USB 这些外设都可以,只是此处使用的是串口

出0入0汤圆

发表于 2014-9-28 18:17:55 | 显示全部楼层
搬过来学习!

出30入0汤圆

发表于 2014-9-28 20:58:24 | 显示全部楼层
我的一百楼,学习 顶
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-6 00:59

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表