基于PIC16F526的沙盘交通灯控制器设计与实现
1. 项目概述为你的沙盘模型打造一个智能交通灯控制器如果你和我一样是个模型火车和沙盘场景的爱好者那你肯定不满足于只有火车在轨道上跑。一个完整的微缩世界怎么能少了公路和穿梭其间的汽车呢而公路场景的灵魂往往就凝聚在那个小小的十字路口上。静态的模型车固然精致但一旦加上几盏能按真实逻辑循环变化的交通信号灯整个场景的“生命感”和“故事感”瞬间就上来了。那种看着红灯亮起、车辆想象中的停下绿灯通行、路口恢复繁忙的满足感是静态模型无法给予的。市面上当然有成品的交通灯控制器可以买但价格不菲功能也往往固定。自己动手做一个不仅成本可控更重要的是你可以完全掌控它的逻辑——从简单的红绿黄交替到更复杂的带转向灯、行人信号甚至根据“车流量”通过传感器调整时长这一切都取决于你的设计和编程。今天我要分享的就是这样一个从硬件设计到软件编程完全自主的沙盘模型交通灯控制器项目。它基于一颗经典的微控制器电路简洁明了代码逻辑清晰可调非常适合有一定电子基础和动手能力的模友来复现和定制。无论你的沙盘是N比例还是HO比例这个方案的核心思想都是通用的。2. 核心硬件设计与选型解析自己动手做控制器第一步永远是硬件规划。硬件是骨架决定了系统的稳定性、扩展性和成本。我们的目标是在保证可靠性的前提下尽可能简化硬件把复杂的逻辑交给软件去实现这也是现代嵌入式开发的普遍思路。2.1 驱动核心为什么选择PIC16F526在众多微控制器中我选择了Microchip的PIC16F526。这并非盲目跟风而是基于几个非常实际的考量恰到好处的资源它拥有12个I/O口对于控制一个标准十字路口的四组灯每组红、黄、绿三色来说刚好够用需要12个输出。内部集成了RC振荡器省去了外部晶振进一步简化了电路。足够的驱动能力其I/O口在5V电压下的拉电流和灌电流典型值可达25mA。这意味着每个引脚可以直接驱动一个普通的LED灯珠无需额外的驱动芯片这对于简化电路至关重要。成本与易用性PIC16F系列是经久不衰的经典型号价格低廉开发工具编程器普及相关的资料和社区支持也非常丰富。对于这样一个功能明确的项目使用它性价比极高。封装合适采用DIP双列直插封装非常适合在面包板上进行原型验证也方便手工焊接对爱好者非常友好。注意虽然PIC16F526的I/O口可以直接驱动LED但务必查阅数据手册确认其绝对最大额定值。单个引脚的电流不要长期超过20mA所有I/O口的总电流也有上限。我们的设计会通过限流电阻将电流控制在安全范围内。2.2 电源方案从模型轨道的12V到芯片需要的5V模型火车沙盘最普遍的电源就是直流12V-16V用于控制轨道上的火车。我们的控制器需要从这个电源系统中取电。电压转换PIC16F526需要稳定的5V工作电压。因此一个线性稳压器如经典的LM7805是必不可少的。它的作用是将12V-16V的输入电压稳定地降至5V输出。输入输出滤波为了抑制电源噪声确保微控制器稳定工作必须在稳压器的输入和输出端分别加上滤波电容。典型配置是输入端一个100μF的电解电容滤除低频波动并联一个0.1μF的陶瓷电容滤除高频噪声输出端同理。这看似是小细节却是系统稳定不重启的关键。功耗考虑线性稳压器如7805的原理是将多余的电压以热量的形式耗散掉。假设输入14V输出5V为整个系统提供100mA电流那么稳压器上的功耗就是 (14V-5V) * 0.1A 0.9W。这会产生一定的热量选择TO-220封装的7805并适当留出散热空间是必要的。如果追求高效可以考虑使用DC-DC降压模块但成本和电路复杂度会略有增加。2.3 信号灯接口与驱动电路设计这是硬件与沙盘场景直接对话的部分设计需要兼顾通用性和安全性。LED灯珠特性市面上常见的模型交通灯组件通常是三色红、黄、绿LED集成在一个小灯柱里。它们通常采用“共阳”或“共阴”的连接方式。我手头这个就是共阳接法三个LED的阳极正极连接在一起引出作为公共端三个阴极负极分别独立引出对应红、黄、绿。原始驱动问题这类灯柱通常内置一个限流电阻如1kΩ设计用于直接接在12V电源上。计算一下假设LED正向压降约2V那么电流 I (12V - 2V) / 1000Ω 10mA亮度基本够用。但如果我们直接用PIC的5V I/O口去驱动这个带1kΩ电阻的灯柱电流会变得非常小I (5V - 2V) / 1000Ω 3mA灯光会非常暗淡。改造方案因此我们需要对灯柱进行小小的“改造”移除那个内置的1kΩ电阻。然后在每一个LED的阴极即连接到PIC I/O口的那条线上串联一个阻值更小的限流电阻。计算新的电阻值目标电流设为15mA在PIC驱动能力内且亮度足够LED压降2VPIC输出高电平约5V。那么电阻 R (5V - 2V) / 0.015A 200Ω。考虑到实际电压波动和留有余量选择270Ω或330Ω的标准电阻是非常合适的。这样每个LED都能被PIC的I/O口以合适的亮度直接驱动。接口定义在PCB上我会为每一组交通灯设计一个4Pin的接口Pin15V接LED公共阳极Pin2-4分别接红、黄、绿LED的阴极通过各自的270Ω电阻连接到PIC的I/O口。这样用杜邦线就能轻松连接到沙盘上的灯柱。2.4 扩展功能与调试接口预留一个好的设计要考虑到未来和当下调试的便利。编程接口ICSP我强烈推荐在PCB上预留一个6Pin的ICSP在线串行编程接口。这意味着你可以把编程器如PICKit直接连接到做好的电路板上给PIC芯片烧录程序而无需每次都把芯片拔下来。这大大简化了开发调试流程。如果不想用这个功能不焊接这个接口的排针即可。功能选择跳线/开关我设置了一个两位的拨码开关SV2。它的作用是切换控制器的工作模式。比如模式一正常的红-绿-黄-红循环模式二黄灯闪烁常用于夜间模式或故障指示。通过硬件开关切换比修改程序更方便。功能扩展按钮板上还预留了一个轻触开关。它的作用可以很灵活比如在正常循环模式下短按作为手动切换相位方便调试或者在未来升级的程序中长按用于进入时间参数设置模式。预留硬件为软件升级打开空间。3. 电路原理与PCB设计实战有了清晰的方案接下来就是把思路转化为具体的电路图和一块实实在在的电路板。这个过程是电子DIY中最有成就感的部分之一。3.1 原理图绘制要点绘制原理图时我使用的是KiCad这款免费开源软件当然你用Eagle、Altium Designer等任何熟悉的工具都可以。关键是要清晰、规范。核心电路微控制器部分放置PIC16F526将VDD和VSS即电源和地引脚正确连接。虽然芯片有内部振荡器但为了稳定我在OSC1引脚对地接了一个20pF的电容根据数据手册推荐。所有未使用的I/O口我通过一个10kΩ电阻上拉到5V防止其悬空产生不确定状态。电源部分LM7805是核心。输入脚IN接来自沙盘电源的12V-16V正极并接上输入滤波电容C1: 100μF C2: 0.1μF。输出脚OUT输出5V同样接上输出滤波电容C3: 100μF C4: 0.1μF。地脚GND直接接电源地。驱动部分12个I/O口如RA0, RA1...每个口连接一个270Ω的电阻R1-R12电阻的另一端连接到对应的输出接口插座如LED_RED1, LED_YELLOW1...。接口电路电源输入接口J1一个2Pin的接线端子定义好正负极。编程接口J2标准的6Pin ICSP接口引脚顺序对应编程器的VPP编程电压、VDD电源、GND地、PGC时钟、PGD数据。模式开关SW1一个两位拨码开关一端接地另一端通过上拉电阻接5V中间引脚连接到PIC的某个I/O口如RB0。当开关断开时该I/O口读到高电平闭合时读到低电平。程序通过检测这个电平来判断模式。功能按钮SW2轻触开关一端接地另一端通过一个10kΩ电阻上拉到5V并连接到PIC的另一个I/O口如RB1。平时该口为高电平按下按钮时变为低电平。灯组输出接口J3, J4两个4Pin的排针插座用于连接两组交通灯。引脚定义务必清晰标注在原理图上。3.2 PCB布局与布线经验谈画好原理图只是第一步把元件合理地摆放在电路板上并连接起来才是真正的挑战。这里有很多经验技巧。布局优先原则电源路径最短首先放置7805稳压芯片让它靠近电源输入接口J1。输入和输出滤波电容必须紧贴7805的引脚放置尤其是0.1μF的陶瓷电容要尽可能靠近引脚才能有效滤除高频噪声。核心器件居中将PIC16F526放在板子中央位置这样它的引脚可以相对均匀地辐射出去连接其他部分减少走线交叉。接口靠边所有对外接口电源输入、编程口、灯组输出都尽量布置在PCB板的边缘方便接线和插拔。按功能分区可以把板子想象成几个区域电源区7805及周边电容、MCU核心区、驱动输出区12个270Ω电阻和输出接口、扩展功能区开关和按钮。同类元件摆放在一起。布线黄金法则电源线加粗12V输入线和5V主干线的走线宽度至少要在24mil0.6mm以上如果空间允许加到30-40mil更好以减小线路阻抗提供稳定电流。信号线与电源线避免平行如果不得不平行尽量拉开距离或中间用地线隔离防止噪声耦合。形成完整的地平面在双面PCB的设计中我会将底层Bottom Layer尽可能用作完整的地平面Ground Plane。这能提供极低的接地阻抗屏蔽噪声是提高系统稳定性的最有效手段之一。所有器件的地引脚都通过过孔Via直接连接到这个地平面。去耦电容的走线给PIC的VDD和VSS引脚之间加一个0.1μF的陶瓷去耦电容这个电容的走线一定要短理想情况是电容的两个焊盘直接通过过孔连接到芯片电源引脚的正下方。为手工制作优化元件间距考虑到手工焊接所有元件之间的间距要留足。特别是IC插座、电解电容这些“大个子”别摆得太挤。焊盘尺寸适当加大通孔元件的焊盘尺寸比如直径扩大到62mil这样焊接时更容易也不容易因过热而脱落。丝印清晰在丝印层Silkscreen清晰标注每个元件的编号如R1, C1、接口定义如“12V IN”、“RED1”、开关功能如“MODE: NORM/FLASH”。这块板子将来是你自己调试和使用的清晰的标注能省去无数翻看原理图的麻烦。我的第一版PCB就是遵循以上原则设计的尺寸控制在大概6cm x 4cm对于这个功能来说非常紧凑。使用标准的直插元件DIP焊接难度适中。当然如果追求极致迷你化可以全部改用SMD贴片元件但那需要热风枪和更精细的焊接手艺对于大多数爱好者来说直插元件的可维护性更好。4. 软件逻辑与程序编写详解硬件是躯体软件才是灵魂。交通灯控制器的所有智能行为都依赖于我们写入PIC16F526中的程序。我选择用汇编语言Assembly来编写因为它能让我对芯片的每一个时钟周期和内存字节都有精准的控制特别适合这种对时序有严格要求的小型嵌入式应用。当然用C语言开发会更快捷可读性更好这取决于你的偏好。4.1 状态机理解交通灯控制的核心思维编程不是一上来就写代码而是先理清逻辑。控制交通灯最经典、最清晰的模型就是“状态机”。我们可以把十字路口两组灯南北向和东西向的工作循环分解成几个明确的状态。假设我们模拟一个最简单的双向两车道十字路口状态1南北绿灯东西红灯持续30秒。让南北方向车辆通行。状态2南北黄灯东西红灯持续5秒。警告南北方向车辆即将禁行。状态3南北红灯东西绿灯持续25秒。切换为东西方向车辆通行。状态4南北红灯东西黄灯持续5秒。警告东西方向车辆即将禁行。然后跳转回状态1如此循环。在每一个状态里程序只需要稳定地输出对应的电平到12个I/O口例如状态1下南北向绿灯引脚输出低电平点亮红灯输出高电平熄灭东西向红灯输出低电平绿灯输出高电平并维持一段特定的时间。状态机编程的魅力就在于你只需要定义好状态和跳转条件程序结构会非常清晰。4.2 汇编程序框架解析下面我勾勒出程序的核心框架并解释关键部分。请注意这不是完整代码而是逻辑说明。初始化Initialization; 伪代码示意 MAIN: BANKSEL TRISA ; 选择包含方向寄存器的存储区 MOVLW b11110000 ; 假设RA0-RA3为输出接LEDRA4-RA7为输入接开关等 MOVWF TRISA MOVLW bxxxxxx ; 类似地设置TRISB定义输入输出口 MOVWF TRISB BANKSEL PORTA ; 切回数据存储区 CLRF PORTA ; 初始化所有输出为0低电平 CLRF PORTB这段代码在芯片上电后执行一次目的是配置好哪些引脚是输出用来控制LED哪些是输入用来读取开关状态。同时把所有灯初始化为熄灭状态。主循环与延时控制 主程序是一个无限循环核心是顺序执行各个状态并用精确的延时函数来控制每个状态的持续时间。MAIN_LOOP: ; 读取模式开关连接在RB0 BTFSS PORTB, 0 ; 测试RB0是否为1开关断开正常模式 GOTO FLASH_MODE ; 如果是0开关闭合跳转到闪烁模式 ; 正常模式 CALL STATE_N_GREEN_E_RED ; 调用“南北绿东西红”状态函数 CALL DELAY_30S ; 延时30秒 CALL STATE_N_YELLOW_E_RED ; 调用“南北黄东西红”状态函数 CALL DELAY_5S CALL STATE_N_RED_E_GREEN CALL DELAY_25S CALL STATE_N_RED_E_YELLOW CALL DELAY_5S GOTO MAIN_LOOP ; 跳回循环开始这里的CALL DELAY_XX是调用一个延时子程序。在汇编中精确的长延时通常通过多层循环嵌套来实现。你需要根据芯片的指令周期和时钟频率如内部4MHz RC振荡器来计算循环次数。状态函数实现 每个状态函数非常简单就是设置I/O口的输出值。STATE_N_GREEN_E_RED: ; 假设RA0:北绿 RA1:北黄 RA2:北红 RA3:东绿 RA4:东黄 RA5:东红 ; 共阳接法输出0点亮LED输出1熄灭LED MOVLW b110110 ; 二进制北绿(RA0)0亮 北黄(RA1)1灭 北红(RA2)1灭 ; 东绿(RA3)1灭 东黄(RA4)1灭 东红(RA5)0亮 MOVWF PORTA RETURN通过改变MOVLW后面的二进制数值就能轻松定义任何一个状态下的灯光组合。闪烁模式与按钮检测FLASH_MODE: ; 所有方向黄灯闪烁 CALL STATE_ALL_YELLOW_ON CALL DELAY_0_5S ; 亮0.5秒 CALL STATE_ALL_LIGHTS_OFF CALL DELAY_0_5S ; 灭0.5秒 ; 在闪烁间隙可以检测功能按钮连接在RB1 BTFSS PORTB, 1 ; 检测按钮是否被按下低电平 CALL BUTTON_PRESSED_HANDLER ; 如果按下调用按钮处理函数 GOTO FLASH_MODE ; 继续闪烁循环 BUTTON_PRESSED_HANDLER: ; 这里可以编写按钮按下后的处理逻辑 ; 例如在正常模式下按一下快速切换到下一个状态手动控制 ; 或者长按进入时间设置模式需要更复杂的逻辑和显示设备 ; 目前可以先实现一个简单的“手动步进”功能 ; ... RETURN闪烁模式通常作为一个独立的工作模式。在闪烁的循环中我插入了对功能按钮的检测。这是一种“非阻塞式”的检测不会影响闪烁的时序。4.3 时间参数的可调化设计最初的程序把延时时间如30秒、5秒写死在代码里每次修改都需要重新编译和烧录很不方便。一个更高级的设计是让这些时间参数可调。使用变量存储时间在芯片的数据存储器RAM中定义几个变量比如green_time,yellow_time。主循环的延时不再用固定的DELAY_30S而是调用一个通用的延时函数DELAY_GENERIC这个函数的延时长度由green_time变量的值决定。如何调整变量这就需要用到我们预留的那个功能按钮和一个简单的设置界面。一个常见的做法是长按按钮3秒进入“设置模式”。此时所有交通灯熄灭或许用某个LED的闪烁来指示当前正在设置哪个参数例如南北绿灯时间。短按按钮增加时间比如每次加5秒再次长按切换到下一个参数东西绿灯时间、黄灯时间等。所有参数设置完成后长按退出设置模式新参数被保存到芯片的EEPROM中PIC16F526有64字节EEPROM这样即使断电也不会丢失。 实现这个功能程序复杂度会大大增加需要处理按钮的短按、长按识别状态菜单的切换EEPROM的读写等。但这将把你的控制器提升到一个“准商业级”的灵活度。5. 原型制作、调试与问题排查设计完成程序写好最激动人心的环节就是让想法变成现实。焊接、调试、解决问题这个过程充满了挑战和乐趣。5.1 焊接与组装注意事项先矮后高先里后外焊接元件时遵循这个顺序。先焊接高度最低的贴片电阻、陶瓷电容然后是IC插座、拨码开关最后是较高的电解电容、接线端子和按钮。这样可以避免先焊高的元件妨碍后面焊接低的元件。7805的散热LM7805在压差大、电流不小的情况下会发热。焊接时确保其金属背板与PCB上的焊盘接触良好。如果条件允许可以在PCB背面7805对应的位置留出一片铜皮作为散热面甚至加装一个小型散热片。极性元件电解电容、LED灯柱都有正负极IC插座有缺口方向指示。焊接前务必再三确认接反了轻则不工作重则烧毁元件。我的习惯是在PCB丝印上给正极焊盘画上“”号给IC插座的缺口位置也清晰标出。电源首次上电焊接完成后先不要插芯片用万用表二极管档或电阻档仔细检查5V输出7805的OUT脚与地GND之间是否短路。这是最重要的安全检查可以防止因焊接短路而烧毁稳压器或后续芯片。确认无误后接通12V电源测量7805的输出脚应该是稳定的5V±0.2V。5.2 上电调试流程实录裸板测试插上PIC芯片注意方向连接12V电源。此时程序应该开始运行。用万用表电压档或逻辑笔更直观去测量连接LED的各个I/O口如RA0, RA1等。你应该能看到这些引脚的电压按照你程序设定的逻辑在高电平~5V和低电平~0V之间周期性地变化。这说明MCU核心和程序运行基本正常。连接单个LED测试不要一下子把四组灯全接上。先找一个普通的LED记得串联一个270Ω电阻将其正极接板子的5V负极接板子的一个输出口如“北绿灯”接口。观察LED是否按照预期亮灭。这样可以逐一验证12个输出通道是否都工作正常。连接模型灯柱确认所有输出口都正常后断开电源连接一组三个灯模型交通灯柱。务必确认你已经移除了灯柱内置的1kΩ电阻并且你的PCB上已经焊接了270Ω的限流电阻上电后观察红、黄、绿三色LED是否能被正确点亮。由于是共阳接法当控制器输出低电平时对应的LED点亮。模式切换测试拨动模式开关SV2观察交通灯是否从正常循环模式切换到黄灯同步闪烁模式。按钮功能测试在正常模式下尝试短按功能按钮看看是否实现了你预设的功能比如手动切换相位。5.3 常见问题与排查技巧实录在制作和调试过程中你几乎一定会遇到一些问题。下面是我踩过坑后总结的排查清单问题现象可能原因排查步骤与解决方法完全无反应电源指示灯也不亮1. 电源接反或未接通。2. 7805输入输出短路或损坏。3. PCB电源走线有断裂。1. 检查12V电源适配器是否正常工作极性是否正确。2.断电下用万用表测7805输入-地、输出-地电阻排除短路。测输入电压是否达到12V。3. 仔细检查从电源接口到7805再到VCC网络的铜箔走线是否连通。7805发热异常严重1. 后级电路存在短路特别是5V对地。2. 输入电压过高如超过18V。3. 负载电流过大但本项目通常不会。1.立即断电重点检查所有连接到5V的元件特别是IC、电容有无焊反、焊连。断开PIC芯片看是否还发热。2. 确保输入电压在标称范围内9V-15V为宜。3. 计算总负载电流12个LED * 15mA 180mA在7805承受范围内。PIC芯片发烫1. 电源接反VDD和VSS反接是致命的。2. I/O口对地或对电源短路。3. 程序跑飞I/O口状态冲突。1.立即断电检查芯片方向、电源引脚焊接。2. 用万用表检查每个I/O口对地、对5V的电阻排除短路。3. 重新烧录一个最简单的“所有I/O口输出高电平”的程序测试。部分LED不亮或常亮1. 该路限流电阻虚焊、阻值错误或损坏。2. PIC对应的I/O口配置错误应设为输出。3. 程序中对应该LED的控制逻辑有误。4. LED灯珠本身损坏或接线错误。1. 测量该路限流电阻两端电压正常点亮时电阻两端应有约3V压降。2. 检查程序初始化部分确认该I/O口的方向寄存器TRISx被正确设置为输出0。3. 用调试器单步运行程序或编写一个让该I/O口周期性翻转的测试程序。4. 交换测试将不亮的LED接到一个确认正常的输出口上测试。灯光闪烁不稳定或程序跑飞1. 电源滤波不良纹波过大。2. 复位电路不稳定虽然PIC16F526内置了上电复位但复杂环境可能不够。3. 程序中的延时函数计算不准确或中断被意外打开。1. 用示波器观察5V电源线上的波形看是否有大幅波动。确保0.1μF陶瓷电容紧贴7805和PIC的电源引脚焊接。2. 考虑在PIC的MCLR引脚复位脚增加一个10kΩ电阻上拉到5V并加一个0.1μF电容到地构成简单的外部复位电路。3. 检查程序确认没有误操作中断相关的寄存器。重新校准延时循环的计数值。模式开关或按钮不起作用1. 上拉电阻未焊接或虚焊。2. 程序中对输入口的配置错误应设为输入。3. 读取I/O口状态的指令或逻辑有误。1. 测量模式开关或按钮未按下时对应PIC引脚的电平是否为高~5V按下时是否为低~0V。2. 检查程序确认对应I/O口的方向寄存器被设置为输入1。3. 在程序中读取输入口前是否需要先给对应锁存器LATx写1查阅数据手册确认I/O口读操作的正确方法。这个排查过程本身就是极好的学习经历。当你用万用表和逻辑分析仪甚至一个简单的LED探针一步步找到问题根源并解决时你对电路和程序的理解会深刻得多。6. 项目总结与未来扩展思路经过从原理设计、PCB绘制、焊接调试到程序编写的一系列工作一个完全自主可控的沙盘交通灯控制器就实实在在地运行在你面前了。看着它按照你设定的逻辑一丝不苟地指挥着微缩世界里的交通那种成就感远超购买一个成品。这个项目的价值不仅在于最终的作品更在于整个过程让你深入理解了嵌入式系统开发的全链路从需求分析、器件选型、电路设计到PCB制作、软件编程、硬件调试。这个原型已经实现了核心功能但它就像一个开放的平台还有巨大的潜力可以挖掘驱动能力升级目前的方案直接使用PIC的I/O口驱动LED如果想驱动功率更大的灯珠比如用于室外场景照明的大功率LED甚至是模拟老式信号灯的微型白炽灯泡就需要增加驱动电路。最简单的办法是使用晶体管如MOSFET或达林顿阵列芯片如ULN2003来扩流。PIC的I/O口只提供控制信号大电流由这些驱动器件提供。控制逻辑复杂化实现更多国家的交通灯序列例如欧洲常见的“红 - 红黄 - 绿 - 黄 - 红”。这只需要修改软件状态机即可。甚至可以加入行人请求按钮、传感器检测如用红外对管模拟车辆检测来制造动态交通流让沙盘场景更加生动。参数设置人性化如前所述开发一个通过按钮和LED指示灯进行交互的菜单系统来现场调整绿灯、黄灯的持续时间而无需连接电脑重新编程。这需要更复杂的程序结构和状态管理是锻炼编程能力的好课题。通信与联网如果沙盘上有多个路口可以让多个控制器通过简单的串口UART或者I2C总线通信实现协调联动比如“绿波带”效果。这需要定义简单的通信协议将项目提升到多机系统的层次。是否要继续深入这些扩展完全取决于你的兴趣和需求。但无论如何这个基础版本已经提供了一个稳定、可靠、完全透明的起点。它所有的电路图和代码都是开放的你可以任意修改、复制和分享。这就是DIY最大的乐趣所在——你不是一个被动的消费者而是整个世界的创造者和主宰者。希望这个详细的分享能给你带来启发和帮助祝你制作顺利享受属于你的创造过程。