上下移动的层

本文介绍了一个基于HTML与JavaScript实现的滚动图片案例,该案例中图片能够跟随页面滚动而平滑移动,并支持用户拖拽重新定位图片位置。文章通过具体的代码展示了如何在不同浏览器环境下(如IE和NS)实现这一功能。

<html>
<head>
<title>滚动图</title>

<style type="text/css">
#floater {
position: absolute;
left: 500;
top: 146;
width: 176;
visibility: visible;
z-index: 10;
}
-->
</style>

</head>
<body>
<div ID="floater" style="left: 800px; top: 300px">
<p align="center">
<img src="http://g1a111.mail.163.com/netfolder/servlet/nfapp/GetFile?sid=UCMwLfnnAoGmrwAJCunnRZHlYrrWAFrS&mid=1tbimBCZiUZG7950fgAAsj" width="127" height="150" onClick="javascript:window.open(this.src);" style="CURSOR: pointer" onload="return imgzoom(this,550)"> adsd
</p>
</div>

<script LANGUAGE="JavaScript">
self.onError=null;
currentX = currentY = 0;
whichIt = null;
lastScrollX = 0; lastScrollY = 0;
NS = (document.layers) ? 1 : 0;
IE = (document.all) ? 1: 0;
<!-- STALKER CODE -->
function heartBeat() {
if(IE) { diffY = document.body.scrollTop; diffX = document.body.scrollLeft; }
if(NS) { diffY = self.pageYOffset; diffX = self.pageXOffset; }
if(diffY != lastScrollY) {
percent = .1 * (diffY - lastScrollY);
if(percent > 0) percent = Math.ceil(percent);
else percent = Math.floor(percent);
if(IE) document.all.floater.style.pixelTop += percent;
if(NS) document.floater.top += percent;
lastScrollY = lastScrollY + percent;
}
if(diffX != lastScrollX) {
percent = .1 * (diffX - lastScrollX);
if(percent > 0) percent = Math.ceil(percent);
else percent = Math.floor(percent);
if(IE) document.all.floater.style.pixelLeft += percent;
if(NS) document.floater.left += percent;
lastScrollX = lastScrollX + percent;
}
}
<!-- /STALKER CODE -->
<!-- DRAG DROP CODE -->
function checkFocus(x,y) {
stalkerx = document.floater.pageX;
stalkery = document.floater.pageY;
stalkerwidth = document.floater.clip.width;
stalkerheight = document.floater.clip.height;
if( (x > stalkerx  &&  x < (stalkerx+stalkerwidth))  &&  (y > stalkery  &&  y < (stalkery+stalkerheight))) return true;
else return false;
}
function grabIt(e) {
if(IE) {
whichIt = event.srcElement;
while (whichIt.id.indexOf("floater") == -1) {
whichIt = whichIt.parentElement;
if (whichIt == null) { return true; }
}
whichIt.style.pixelLeft = whichIt.offsetLeft;
whichIt.style.pixelTop = whichIt.offsetTop;
currentX = (event.clientX + document.body.scrollLeft);
currentY = (event.clientY + document.body.scrollTop);
} else {
window.captureEvents(Event.MOUSEMOVE);
if(checkFocus (e.pageX,e.pageY)) {
whichIt = document.floater;
StalkerTouchedX = e.pageX-document.floater.pageX;
StalkerTouchedY = e.pageY-document.floater.pageY;
}
}
return true;
}
function moveIt(e) {
if (whichIt == null) { return false; }
if(IE) {
newX = (event.clientX + document.body.scrollLeft);
newY = (event.clientY + document.body.scrollTop);
distanceX = (newX - currentX); distanceY = (newY - currentY);
currentX = newX; currentY = newY;
whichIt.style.pixelLeft += distanceX;
whichIt.style.pixelTop += distanceY;
if(whichIt.style.pixelTop < document.body.scrollTop) whichIt.style.pixelTop = document.body.scrollTop;
if(whichIt.style.pixelLeft < document.body.scrollLeft) whichIt.style.pixelLeft = document.body.scrollLeft;
if(whichIt.style.pixelLeft > document.body.offsetWidth - document.body.scrollLeft - whichIt.style.pixelWidth - 20) whichIt.style.pixelLeft = document.body.offsetWidth - whichIt.style.pixelWidth - 20;
if(whichIt.style.pixelTop > document.body.offsetHeight + document.body.scrollTop - whichIt.style.pixelHeight - 5) whichIt.style.pixelTop = document.body.offsetHeight + document.body.scrollTop - whichIt.style.pixelHeight - 5;
event.returnValue = false;
} else {
whichIt.moveTo(e.pageX-StalkerTouchedX,e.pageY-StalkerTouchedY);
if(whichIt.left < 0+self.pageXOffset) whichIt.left = 0+self.pageXOffset;
if(whichIt.top < 0+self.pageYOffset) whichIt.top = 0+self.pageYOffset;
if( (whichIt.left + whichIt.clip.width) >= (window.innerWidth+self.pageXOffset-17)) whichIt.left = ((window.innerWidth+self.pageXOffset)-whichIt.clip.width)-17;
if( (whichIt.top + whichIt.clip.height) >= (window.innerHeight+self.pageYOffset-17)) whichIt.top = ((window.innerHeight+self.pageYOffset)-whichIt.clip.height)-17;
return false;
}
return false;
}
function dropIt() {
whichIt = null;
if(NS) window.releaseEvents (Event.MOUSEMOVE);
return true;
}
<!-- DRAG DROP CODE -->
if(NS) {
window.captureEvents(Event.MOUSEUP|Event.MOUSEDOWN);
window.onmousedown = grabIt;
window.onmousemove = moveIt;
window.onmouseup = dropIt;
}
if(IE) {
document.onmousedown = grabIt;
document.onmousemove = moveIt;
document.onmouseup = dropIt;
}
if(NS || IE) action = window.setInterval("heartBeat()",1);
</script>

1<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>
1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>
1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>1<br/>

</body>
</html>

<think>好的,我需要帮助用户实现使用STM32控制两电梯上下移动的功能。首先,我得理解用户的需求。他们想要控制一个两电梯,可能包括电机控制、楼检测、按键响应以及安全机制等部分。我需要结合提供的引用内容,特别是关于STM32的GPIO、定时器和中断功能的信息,来设计一个可行的方案。 首先,根据引用[1],STM32的GPIO口功能强大,每个GPIO有7个寄存器和8种工作模式,这可以用于连接各种传感器和执行器。比如,楼检测可能需要红外传感器或磁感应开关,这些可以连接到GPIO输入口。同时,电机的正反转控制可能需要GPIO输出口来驱动继电器或电机驱动器。 其次,引用[2]提到了编码器的工作原理和高速计数器程序。电梯的位置检测可能需要编码器来精确测量电机的旋转,进而确定电梯所在的楼。STM32的定时器功能可以用来处理编码器的信号,实现精确的计数和方向判断。 然后,引用[3]指出使用STM32F407单片机,具有高性能和低功耗的特点,适合电梯控制系统。需要确认用户是否使用相同型号,但不管怎样,STM32系列的处理能力足够应对两电梯的控制需求。 接下来,我需要考虑系统的各个模块: 1. **电机控制**:使用H桥电路或电机驱动器控制直流电机的正反转,对应电梯的上下行。需要配置GPIO输出模式,并可能使用PWM进行速度控制。这里需要确保电机驱动电路的安全,避免短路或过流。 2. **楼检测**:采用红外传感器或磁开关在每安装,当电梯到达指定楼时触发信号。STM32的GPIO输入模式可以检测这些信号,结合中断功能实现实时响应。 3. **按键处理**:电梯内外部的呼叫按钮需要去抖动处理,可以通过外部中断或定时器扫描实现。中断方式能提高响应速度,确保及时处理用户请求。 4. **状态显示**:使用LED或数码管显示当前楼,可能需要GPIO或SPI/I2C接口驱动显示模块。 5. **安全机制**:包括超重检测、门状态检测和紧急停止。超重传感器可以通过模拟输入或数字信号接入,门状态检测同样需要GPIO输入,紧急停止按钮则触发中断立即停止电机。 在软件设计方面,主循环需要处理按键扫描、状态更新和电机控制。中断服务程序用于处理紧急停止、楼到达和按键事件。例如,当电梯到达目标楼时,触发中断停止电机并开门。同时,状态机模型可以管理电梯的运行状态,如停止、上行、下行等。 需要注意的是,定时器的精确控制(如引用[1]提到的)可以用于生成PWM信号控制电机速度,或者进行超时检测,确保电梯在预期时间内到达目标楼,否则触发故障处理。 可能遇到的挑战包括电机控制的稳定性、楼检测的准确性以及多任务处理的实时性。需要合理分配中断优先级,避免冲突,并确保关键任务(如安全检测)能够及时响应。 总结来说,方案需要结合硬件模块的连接和软件逻辑的设计,充分利用STM32的GPIO、定时器和中断功能,确保电梯系统的可靠性和安全性。同时,用户可能需要参考具体的STM32型号手册,配置相应的寄存器和外设参数,以实现最佳性能。</think>### STM32控制两电梯上下移动实现方案 #### 一、硬件设计 1. **电机控制模块** - 使用H桥电路或电机驱动芯片(如L298N)控制直流电机正反转,对应电梯升降动作 - 配置STM32的**GPIO输出模式**控制电机方向(例:PA0=高电平/PWM时正转,PA1=高电平/PWM时反转)[^1] 2. **楼检测模块** - 在1和2安装红外传感器/磁感应开关 - 使用**GPIO输入模式**检测楼信号(例:PC0连接1传感器,PC1连接2传感器) 3. **按键模块** - 设置4个外部按键:1上行、2下行、轿厢内1/2选择 - 采用**外部中断模式**实现快速响应,配置上拉电阻防抖动[^2] 4. **状态显示模块** - 使用LED数码管显示当前楼(通过GPIO或SPI接口驱动) 5. **安全机制模块** - 超重检测(压力传感器模拟信号输入ADC) - 门状态检测(限位开关接入GPIO) - 紧急停止按钮(最高优先级外部中断) #### 二、软件设计 1. **主程序流程图** ```mermaid graph TD A[系统初始化] --> B[检测楼位置] B --> C{有呼叫请求?} C --> |是| D[路径规划] C --> |否| B D --> E[电机启动] E --> F[实时监测位置] F --> G{到达目标?} G --> |是| H[停止电机] H --> I[开门操作] I --> B ``` 2. **关键代码片段** ```c // 电机控制函数 void Motor_Control(Direction dir){ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, (dir == UP) ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, (dir == DOWN) ? GPIO_PIN_SET : GPIO_PIN_RESET); // 使用PWM实现软启动 __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 800); } // 外部中断回调函数 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ if(GPIO_Pin == Floor1_Pin){ current_floor = 1; Stop_Motor(); } else if(GPIO_Pin == Floor2_Pin){ current_floor = 2; Stop_Motor(); } } ``` 3. **定时器配置** 使用TIM3定时器: - 模式:编码器模式(用于电梯位置精确定位) - 分频系数:72MHz/128 - 自动重装载值:65535 - 启用计数器溢出中断[^2] #### 三、调试要点 1. **楼定位校准** 使用增量式编码器时需设置零点校正程序,每次上电后自动寻找基准位置 2. **运动曲线优化** 通过PWM占空比调整实现电梯启停加减速: $$v(t) = v_{max}(1 - e^{-t/\tau})$$ 其中$\tau$为时间常数,控制加速度 3. **抗干扰设计** - 电机电源与MCU电源隔离 - 信号线加磁环滤波 - 软件滤波算法(中位值平均滤波)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值