HSIAO-YANG CHEN 发布的文章

这是我的第一个51项目(很久没写过程序了,顺便活动下大脑,不然要生锈了)。
原理:变化的电场产生变化的磁场,变化的磁场切割线圈产生感应电流。经过全波整流,直接将电平信号送入AT89C2051,利用芯片自带的比较器(P1.0、P1.1)和存放比较结果P3.6。通过轮询P3.6的状态,启动或停止计时中断,每次计时清空计时器,计时时间小于0.1S不显示结果(屏蔽了部分由于干扰而产生的误动作)
电路设计:
3edd751ex9e58693c974a.jpg
焊接完成的电路板:
3edd751ex9e5868ff9385.jpg
51汇编代码:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; AT89C2051通断计时程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 定时器T0溢出周期为10MS,P1.0(同相端)、P1.1(反相端)作为电压比较器
; P3.6为比较器的输出结果,P1.2-P1.7和P3.0、P3.1口(A-DP)为字符输出口,采用共阳显示管。
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 中断入口程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
ORG 0000H ;程序执行开始地址
LJMP MAIN ;跳到标号MAIN执行
ORG 0003H ;外中断0中断程序入口
RETI ;外中断0中断返回
ORG 000BH ;定时器T0中断程序入口
LJMP INTT0 ;跳至INTTO执行
ORG 0013H ;外中断1中断程序入口
RETI ;外中断1中断返回
ORG 001BH ;定时器T1中断程序入口
RETI ;定时器T1中断返回
ORG 0023H ;串行中断程序入口地址
RETI ;串行中断程序返回
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 主 程 序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
MAIN:

MOV R0,#70H ;清70H-77H共8个内存单元
MOV R7,#08H ;
CLEARDISP: MOV @R0,#00H ;
INC R0 ;
DJNZ R7,CLEARDISP ;
MOV 70H,#07H;初始化信息显示
MOV 71H,#06H
MOV 72H,#0AH
MOV 73H,#0BH

MOV TMOD,#01H ;设T0为16位定时器
CLR C ;清进位标志

MAIN1:
LCALL DISPLAY ;调用显示子程序
LCALL DS8MS;调用延迟减少误动作
JB P3.6,START ;P3.6口为1时开启定时器

JC STOP;据进位标志位判断是否关停T0
SJMP MAIN1
STOP:
CLR C;清除标志位
CLR TR0 ;关闭T0定时器
CLR ET0 ;关闭T0中断
CLR EA ;关闭总中断
SJMP MAIN1

START:
JC MAIN1;据标志位情况判断是否需清零重新开启T0
SETB C
MOV R0,#75H
ACALL CLR0 ;计时单元清0
MOV R0,#77H
ACALL CLR0 ;计时单元清0
MOV TL0,#0f0H ;10MS定时初值(T0计时用)
MOV TH0,#0D8H ;10MS定时初值
SETB EA ;总中断开放
SETB ET0 ;允许T0中断
SETB TR0 ;开启T0定时器
SJMP MAIN1


;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 10毫秒计时程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;T0中断服务程序
INTT0: PUSH ACC ;累加器入栈保护
PUSH PSW ;状态字入栈保护
CLR ET0 ;关T0中断允许
CLR TR0 ;关闭定时器T0
MOV A,#0F7H ;中断响应时间同步修正
ADD A,TL0 ;低8位初值修正
MOV TL0,A ;重装初值(低8位修正值)
MOV A,#0d8H ;中断响应时间同步修正
ADDC A,TH0 ;高8位初值修正
MOV TH0,A ;重装初值(高8位修正值)
SETB TR0 ;开启定时器T0
MOV R0,#75H ;指向毫秒计时单元(74H-75H)
ACALL ADD1 ;调用加1程序
CLR C ;清进位标志
CJNE R4,#9Ah,ADDMM ;判断是否等于100毫秒
ADDMM: JC OUTT0 ;小于100毫秒时中断退出
ACALL CLR0 ;大于或等于100毫秒时对毫秒计时单元清0
MOV R0,#77H ;指向秒计时单元(76H-77H)
ACALL ADD1 ;秒计时单元加1秒
CLR C ;清进位标志
CJNE R4,#9Ah,ADDSS ;
ADDSS: JC OUTT0 ;小于100秒时中断退出
ACALL CLR0 ;大于或等于100秒计时单元清0
OUTT0:
MOV R0,#75H
MOV A,@R0
MOV R3,#02H
FOR:INC R0
ORL A,@R0
DJNZ R3,FOR ;小于0.1秒不做输出显示
JZ DIS
MOV 70H,74H
MOV 71H,75H
MOV 72H,76H
MOV 73H,77H
DIS:
POP PSW ;恢复状态字(出栈)
POP ACC ;恢复累加器
SETB ET0 ;开放T0中断
RETI ;中断返回

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 加1子程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
ADD1: MOV A,@R0 ;取当前计时单元数据到A
DEC R0 ;指向前一地址
SWAP A ;A中数据高四位与低四位交换
ORL A,@R0 ;前一地址中数据放入A中低四位
ADD A,#01H ;A加1操作
MOV R4,A;保留用于判断是否进位
DA A ;十进制调整
MOV R3,A ;移入R3寄存器
ANL A,#0FH ;高四位变0
MOV @R0,A ;放回前一地址单元
MOV A,R3 ;取回R3中暂存数据
INC R0 ;指向当前地址单元
SWAP A ;A中数据高四位与低四位交换
ANL A,#0FH ;高四位变0
MOV @R0,A ;数据放入当削地址单元中
RET ;子程序返回
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 清零程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;对计时单元复零用
CLR0: CLR A ;清累加器
MOV @R0,A ;清当前地址单元
DEC R0 ;指向前一地址
MOV @R0,A ;前一地址单元清0
RET ;子程序返回

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 显示程序(70个机器周期+4*20*25*2=4070us) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 显示数据在70H-73H单元内,用4位LED共阳数码管显示,P1.2-P1.7和P3.0、P3.1口(A-DP)输出段码数据,P3.3-P3.5、P3.7口(10ms|100ms|1S|10S)作
; 扫描控制,每个LED数码管亮1MS时间再逐位循环。
DISPLAY: MOV R1,#70H ;指向显示数据首址

;P3.3扫描显示
MOV A,@R1 ;取显示数据到A
MOV DPTR,#TABP3;取段码表地址
MOVC A,@A+DPTR ;查显示数据对应段码
ANL A,#0F7H;显示端口
MOV P3,A;段码和端口放入P3口
MOV A,@R1 ;取显示数据到A
MOV DPTR,#TABP1 ;取段码表地址
MOVC A,@A+DPTR
MOV P1,A ;段码放入P1口
LCALL DL1MS ;显示1MS
INC R1 ;指向下一地址
;P3.4扫描显示
MOV A,@R1
MOV DPTR,#TABP3
MOVC A,@A+DPTR
ANL A,#0EFH
MOV P3,A
MOV A,@R1
MOV DPTR,#TABP1
MOVC A,@A+DPTR
MOV P1,A
LCALL DL1MS
INC R1
;P3.5扫描显示
MOV A,@R1
MOV DPTR,#TABP3
MOVC A,@A+DPTR
ANL A,#0DEH
MOV P3,A
MOV A,@R1
MOV DPTR,#TABP1
MOVC A,@A+DPTR
MOV P1,A
LCALL DL1MS
INC R1
;P3.7扫描显示
MOV A,@R1
MOV DPTR,#TABP3
MOVC A,@A+DPTR
ANL A,#07FH
MOV P3,A
MOV A,@R1
MOV DPTR,#TABP1
MOVC A,@A+DPTR
MOV P1,A
LCALL DL1MS

MOV P3,#0FFH  ;一次显示结束,P3口复位
MOV P1,#0FFH ;P1口复位
RET ;子程序返回
TABP3:  DB 0FFH,0FFH,0FDH,0FDH,0FDH,0FDH,0FDH,0FFH,0FDH,0FDH,0FDH,0FDH
TABP1:  DB 003H,0E7H,093H,0C3H,067H,04BH,00BH,0E3H,003H,043H,047H,00FH
;共阳段码表 "0"  "1"  "2" "3"  "4"  "5" "6"  "7"  "8" "9"  "y"  "b"
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 延时程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;1MS延时程序,LED显示程序用
DL1MS: MOV R6,#14H
DL1: MOV R7,#19H
DL2: DJNZ R7,DL2
DJNZ R6,DL1
RET
;8MS延时程序
DS8MS: ACALL DISPLAY
ACALL DISPLAY
RET

;
END ;程序结束

将以上代码编译链接成.HEX文件,烧入AT89C2051,上机
通电初始化信息:“BY 67”
3edd751ex9e586829ee35.jpg
测试通电时间(显示范围0.1S-99.99S):
3edd751ex9e5867544eb5.jpg
感觉很HAPPY,一直在前进,学无止尽。。。。

这个R1的选择跟输入有关,就比如输入最大12V,输出5V,要使7805不加散热片,那7805上的功率就要小于1W
7805上最大通过的电流要小于 1W/(12-5)V≈0.143A
取I=0.1A 假设Q1的发射极电压为0.7V 那这个R1的取值为 0.7V/0.1A=7Ω (注意电阻的功率)(实际使用时如果7805还是太热可以再加大R1,减小7805通过的最大电流)

Q1的作用是当输入电流小于0.1A时,Q1截止(Vbe<0.1A*7Ω),也就是<100mA的电流全部同7805通过,
当电流大于100mA时(Vbe>0.1A*7Ω),7805还是通过100mA电流,剩下的电流由Q1全包了。
3edd751ex91b5d4a50e46.png
转载于 http://www.ourdev.cn/bbs/bbs_content_all.jsp?bbs_sn=3424851

前些日子,哥笔记本声卡的右声道挂了,于是便拆开分析了一番,大概推测是ALC883芯片损坏了,实在是太杯具了,默哀小螃蟹。

由于损坏的是笔记本声卡模块,一般很难买到合适的替换之,上淘宝搜索了一番,竟然也有拆机单卖的声卡模块的,于是便下手淘了一块。

拆换下来的这一块声卡模块,哥也琢磨着怎么继续玩。经过GOOGLE,搜索到了不少好东东,很多DIY爱好者都已经走在哥的前面啦,都在玩芯片升级
3edd751ex916848006183.jpg3edd751ex916847e1e79e.jpg
通过代换相同引脚功能更高版本的CODE,来提升音质,ALC883属于低端的集成声卡,而ALC888属于中高端的集成声卡,通过一些评论侧面了解到ALC888的音质,于是决定动手试试。

看着这么小块集成声卡芯片,哥迷茫啦,怎么下手呢?整个芯片的面积都不到一个指甲的大小,加之工具实在太有限了,家中就只有一把普通的电烙铁,根本无法完成这种超高难度的焊接,对于焊接贴片,烙铁的温度也是非常关键,温度高了,芯片非常容易坏。于是又得升级装备---恒温焊台。买东西就上淘宝(非广告),看价格合适就下手。于是乎买了不少东西,主要用到工具如下
3edd751ex9166d77338a1.jpg
主角恒温焊台,白光非原装,号称是进口的1321芯,加热效果还不错
3edd751ex9166d7826eb2.jpg
焊完的板子都是焊油,所以需要清洗下
3edd751ex9166d7a0ef71.jpg
装洗板液太好用啦,又有毛刷
3edd751ex9166d7b04acb.jpg
看似多此一举,既然买了就用下,确实看得非常清楚
3edd751ex9166d7cec7f3.jpg
这种焊蜜,焊接的时候一点烟都没有,果然是焊接BGA的必备品
3edd751ex9166d7ddf8a1.jpg
后来卖家电话建议哥买0.5mm的,0.3mm估计太细啦!
3edd751ex91684e72f0ac.jpg
把芯片拆下来了,最好用此吸锡线把焊点清理下
3edd751ex9166d7ed46a9.jpg
这个就是ALC888芯片,大小6mm*6mm

  为了确保把损坏的ALC883取下,且不破坏板子,只能拿小美工刀,将芯片的脚小心翼翼的切下,再用焊台把留在板上的脚焊掉,最后用吸锡线把板上的焊点清理平整,最好再用洗板液清洗下,就像新的一样。接下来就是焊接了,把芯片和板子对上脚,先用烙铁把对角的管脚焊住,在管脚适当加一些焊蜜,烙铁粘住一些焊锡,板子稍倾斜,开始拖焊,先把四个边的管脚都托一遍,再来慢慢拖焊,遇到比较大的焊点,可以借助吸锡线,吸走一部分焊锡,同一边不要拖焊时间过长,基本上托三遍就搞定啦,接下来就是清洗工作了!

  把焊好的声卡模块,安装进机子里。插上电源开机,进入系统没声音,但有提示找到新硬件,打开设备管理器,可以很清楚的看到是ALC888硬件ID,证明此硬件已经被识别。重装完驱动,内置的扬声器还是无法正常输出声音,外接音箱完全OK,音频配置程序相比原机多了很多声道的控制,但是笔记本就2个插孔哪里能支持7.1的声道。看来光升级音频CODE还是不够的,不能和机子的BIOS完全配合好,怎么升级都白搭。现在的这个新声卡对于BIOS来说是无法识别的,BIOS无法控制它的行为。每1个设备ID都是由1个硬件ID+子扩展ID,硬件ID取决于硬件本身,而子扩展ID可以由BIOS进行扩展,子扩展ID帮助驱动识别声卡的功能需求。现在驱动将其识别为支持7.1声道的设备,这显然是错误的,现在的芯片就只是运行在其全功能的状态下,并未对其进行功能删减配置。既然都分析出问题的出处了,要解决就容易啦,莫非就是修改BIOS,使其正确识别新的硬件ID,原来是0883,现在是0888,只要把0883替换成0888,应该就行啦。由于程序的编码都是由低往高,所以0883对应的HEX:8308,用hiew32打开BIOSCODX.ROM(Phoenix BIOS),查找分析替换,把改完的BIOS重新刷机,哇!这下就完美啦,和原来配置界面的差不多只是多了一些DTS特性
3edd751ex9168552dacfb.jpg
内置的扬声器也正常啦!

AWARD ACPITBL 动态法已经研究透了,换研究AMI动态法,由于AMIBIOS主模块1B模块映射到内存是离散的,所以修改的代码最好不要乱跳转,否则极易出现一些无法预知的情况。

1、还是采用XSDT前移、SLIC随后的方法。由于空间限制,所以只能把SLIC加到RSDT里,RSDT长度增加4,即为0X28+0X4=0X2C;接下来就要修正XSDT相关的操作
3edd751ex8c4a7b83eba1.jpg
2、修正XSDT在 RSD PTR的指针,0X100改为0X3C
3edd751ex8c4a7d6c2d3e.jpg
3、修正FACP(相对RSDT 0X200)在XSDT的地址,0X124改为0X3C+0X24=0X60
3edd751ex8c4a7bdf88ff.jpg
4、修正XSDT校验,0X100改为0X3C
3edd751ex8c4a7c68d5f0.jpg
5、修正XSDT增加子表地址,把0X104改为0X40、0X100改为0X3C
3edd751ex8c4a7ca5cb92.jpg
6、以上的步骤完成了XSDT的修正,接下来就是想方设法把SLIC加到RSDT、XSDT中,可以考虑移除一些表的校验如OEMB,换成手工校验
3edd751ex8c4ac8b89afa.jpg
增加SLIC添加代码,移除OEMB的校验代码
3edd751ex8c4a7a715150.jpg
如果空间允许,甚至可以调用RSDT/XSDT增加子表的方法,直接在RSDT和XDST里增加SLIC引用

;忙碌的上班生活,让我们分身乏术,每天下班都还得记得做一件小事关闭计算机。
;人毕竟不是机器,难免有时会因其他琐事而疏忽了正在待机的计算机,造成不环保,所以写了这个程序辅助大家关闭计算机,为节约资源做点贡献!
;“程序名.EXE /I”为注册本程序服务,以后可以随系统运行而运行,一劳永逸;“程序名.EXE /U”为移除本程序服务,你仍可以通过手工运行此程序来获得此服务。
;正常下班关机时间大约为17点,加班下班时间为21点。

#Include <Date.au3>
#NoTrayIcon

Global $afternoon="16:58",$night="20:58"

If $CmdLine[0] > 0 Then
 If StringUpper($CmdLine[1]) ="/I" Then
  If ProcessExists("AutoHalt.EXE") Then
     ProcessClose("AutoHalt.EXE")
  sleep(250)
  EndIf
  FileCopy(@ScriptFullPath,@WindowsDir&"\AutoHalt.EXE",1)
  sleep(250)
  RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "AutoHalt", "REG_SZ", @WindowsDir&"\AutoHalt.EXE")
  Run("AutoHalt.EXE",@WindowsDir)
  MsgBox( 0, "消息", "注册成功,计算机已经启用自动关机服务")
 EndIf
 If StringUpper($CmdLine[1]) ="/U" Then
  RegDelete("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "AutoHalt")
  If ProcessExists("AutoHalt.EXE") Then
     ProcessClose("AutoHalt.EXE")
  sleep(250)
  EndIf
  MsgBox( 0, "消息", "自动关机服务已经成功移除")
 EndIf
 Exit 
EndIf

If WinExists("AutoHalt") Then Exit
AutoItWinSetTitle("AutoHalt")

If _NowTime(4) > $afternoon AND _NowTime(4) < $night Then
 $b = False
Else
 $b = True
EndIf

HotKeySet("^!u", "cancel")

While 1
   sleep(1000*60)
    If _NowTime(4)> $afternoon and _NowTime(4)< $night and $b Then
  $b = False
  halt()
 EndIf
 If _NowTime(4)> $night and not($b) Then
  $b = true
  halt()
 EndIf
WEnd

Func halt()
 $c = MsgBox( 4369, "下班时间到了!", "确定要立即关闭计算机吗?"&@CRLF&"默认将于1分钟后自动关闭计算机 ",60 )
 IF  $c = 1 Then

  IF MsgBox( 4369, "下班时间到了!", "请再次确定是否要立即关闭计算机?" ) = 1 Then
   Shutdown(13)
  EndIf
 EndIf
 IF  $c = -1 Then
  Shutdown(13)
 EndIf
EndFunc

Func cancel()
 If _NowTime(4)< $afternoon  Then
  If $b Then
   $b = False
   ToolTip("下班自动关机已经取消!", 0, 0,"",0,1)
   Sleep(1000)
  Else
   $b = True
   ToolTip("下班自动关机已经启用!", 0, 0,"",0,1)
   Sleep(1000)   
  EndIf
 EndIf
 ToolTip("", 0, 0,"",0,1)
EndFunc