单片机简易电子琴程序

单片机简易电子琴程序,第1张

R5音调延时值R6从内存中读到的数据

9H--TABLE1~11数据20H--TL1初值21H--TH1初值22H--修正后的按键值30H--TABLE1~11地址计数器

0AH--d奏音调延时值0BH--内存地址0CH--读写到内存的数据0DH--按键值0EH--内存器件地址

PORT1   EQU   P1

PORT2   EQU   P2

SCK     BIT   P3.0

SDA  BIT   P3.1

ORG   0H

SJMP  MAIN

ORG   0BH

LJMP  TIME0

ORG   1BH

LJMP  TIME1

ORG   30H

--------------------------------------------------------------------------

MAIN:   CLR   TR0

CLR   TR1

MOV   SP,#4FH

MOV   R0,#100

CLR   P3.4

LCALL DELAY5

MOV   9H,#0

MOV   0AH,#0

MOV   0BH,#0

MOV   0CH,#0

MOV   TMOD,#11H

MOV   IE,#8AH

MOV   0DH,#88H

------------扫描放歌和d奏建------------------------------------

XIAN:   JB    P3.2,QT1    没按下放歌建跳qt1

SETB  P3.4    按下放歌建LED发光

LCALL DELAY1

LCALL DELAY1

JNB   P3.2,$   放歌建没释放原地等待

LCALL DELAY1

LCALL DELAY1

Q1:     LCALL SAO

CJNE  R0,#0,Q11

SJMP  Q1

Q11:    LCALL TRANF

JZ    MAIN

MOV   0DH,A    0DH=按键值

LJMP  SING0

QT1:    JB    P3.3,QT4      没按d奏建跳QT3

SETB  P3.4

LCALL DELAY1

LCALL DELAY1

JNB   P3.3,$   d奏键没释放原地等待

LCALL DELAY1

LCALL DELAY1

QT2:    LCALL SAO

CJNE  R0,#0,QT3

SJMP  QT2

QT3:    LCALL TRANF

CJNE  A,#0BH,QT11 若按键值=11转(B键)MAIN!=11键转QT11

LJMP  MAIN

QT11:   JC    MAIN   若按键值<11转MAIN>11继续

CJNE  A,#0CH,M4  若按键值!=12转M1=12(C键)继续 即C键没按下转M1

MOV   PORT1,#11101111B

JNB   P1.3,$   若C键没释放原地等待

MOV   0BH,#0

LJMP  LOOP    输入乐曲存储并演奏

M4:  LCALL DELAY1

LCALL DELAY1

LCALL RWX80     擦写内存数据全部为1

LJMP  MAIN

QT4:    LJMP  XIAN    返回重新扫描放歌和d奏建

--------------------------------------------------------------------------

RWX80:  CJNE  A,#0DH,MM2  A!=13(D键)转M2若为D键继续D键没按下转M2

MOV   0EH,#0A2H  0EH=162=10100010B0EH为24c16页地址

SJMP  MM

MM2:     CJNE  A,#0EH,MM3  A!=14(E键)转M3E键没按下转M3

MOV   0EH,#0A4H  0EH=164=10100100B

SJMP  MM

MM3:     MOV   0EH,#0A6H  F键按下0EH=166=10100110B

MM:     MOV   0BH,#0

MOV   0CH,#0H

RWX801: LCALL RKX02

LCALL WKX02

INC   0BH

INC   0BH

INC   0BH

INC   0BH

MOV   A,0BH

CJNE  A,#0FFH,MM4

MOV   0BH,#0

MM4:    INC   0CH

INC   0CH

INC   0CH

INC   0CH

CJNE   A,#0H,RWX801

RET

--------读数据------------------------------

RKX02:

LCALL START

MOV   A,#0A0H     24C16寻址10100000写

LCALL WRBYT

LCALL TACK

MOV   A,0BH     发送24c16子地址

LCALL WRBYT

LCALL TACK

LCALL START

MOV   A,#0A1H    24C16寻址10100001读

LCALL WRBYT

LCALL TACK

LCALL WRBYT

LCALL TACK

MOV   10H,R6

LCALL RDBYT

LCALL NOTACK

LCALL WRBYT

LCALL TACK

MOV   11H,R6

LCALL RDBYT

LCALL NOTACK

LCALL WRBYT

LCALL TACK

MOV   12H,R6

LCALL RDBYT

LCALL TACK

MOV   13H,R6

LCALL NOTACK

LCALL STOP

RET

---------写数据-----------------------

WKX02:

MOV   R1,#10H

LCALL START

MOV   A,#0A0H

LCALL WRBYT

LCALL TACK

MOV   A,0BH

LCALL WRBYT

LCALL TACK

MOV   A,0CH

LCALL WRBYT

LCALL TACK

MOV   R0,#4

WKX021: MOV   A,@R1

LCALL WRBYT

LCALL TACK

INC   R1

DJNZ  R0,WKX021

LCALL STOP

LCALL DELAY5

LCALL DELAY5

RET

-------输入乐曲存储并演奏--------------------------------------------

LOOP:   CLR   TR0

CLR   TR1

AAA:    JB    P3.3,LOOP4 d奏键按下 向下执行存储乐曲并演奏 否则转LOOP4继续输入乐曲

LCALL DELAY1

LCALL DELAY1

MOV   0CH,#0

LCALL WBAY    存00结束乐谱

LCALL DELAY1

MOV   0DH,#12

LJMP  SING0     播放d奏的乐曲

LOOP4:  LCALL   SAO

CJNE    R0,#0,KEYIN

LJMP    LOOP

KEYIN:  LCALL TRANF

SWAP  A

MOV   09H,A

SWAP  A

CJNE  A,#0,ZZZ     非0键转ZZZ

CLR   TR1

CLR   TR0

LJMP  ZZZZ      0键转ZZZZ

ZZZ: DEC   A    A为按键值因从1键值音调序号对应TABLE频率表0位置故减1

MOV   22H,A   22H存修正后(A=A-1)的按键值

CLR   C

RLC   A    A*2因TABLE一个单元为2字节(1字),指向该单元的第1个字节

MOV   DPTR,#TABLE

MOVC  A,@A+DPTR

MOV   TH1,A   TH1赋初值

MOV   21H,A   TH1初值存21H

MOV   A,22H

CLR   C

RLC   A    A*2因TABLE一个单元为2字节(1字)

INC   A    指向该单元的第2个字节

MOVC  A,@A+DPTR

MOV   TL1,A  TL1赋初值

MOV   20H,A  TL1初值存20H

MOV   TH0,#0C2H

MOV   TL0,#0F6H

SETB  TR0

SETB  TR1

ZZZZ:   MOV   A,PORT1

ORL   A,#0F0H

CJNE  A,#0FFH,ZZZZ

CLR   TR0

CLR   TR1

MOV   A,0AH     d奏乐谱频率延迟值赋A

CLR   C

RRC   A

CLR   C

RRC   A

CLR   C

RRC   A   d奏乐谱频率延迟值/8

CJNE  A,#0FH,NODE

SJMP  DDD

NODE:   JC    DDD

MOV   A,#0FH  d奏乐谱频率延迟值/8后若>15则=15

DDD:    ORL   09H,A   

MOV   0AH,#0

WWW:&nbsp   MOV   A,09H

MOV   0CH,A

LCALL WBAY

LCALL DELAY5

INC   0BH

LJMP  LOOP

-----频率延时-----------------------------------------

DELAY:  MOV   R7,#125

DLY2:   MOV   R4,#02

DLY3:   MOV   R3,#248

DJNZ  R3,$

DJNZ  R4,DLY3

DJNZ  R7,DLY2

DJNZ  R5,DELAY

RET

---------延时----------------------

DELAY1: MOV   R7,#30

MOV   R6,#0

S1:     DJNZ  R6,$

DJNZ  R7,S1

RET

DELAY5: MOV   R7,#10

MOV   R6,#0

S5:     DJNZ  R6,$

DJNZ  R7,S5

RET

-----扫描按键子程序----------

SAO:    MOV   R0,#4

MOV   R3,#11101111B

MOV   R2,#11111111B

NLINE1: MOV   A,R3

MOV   PORT1,A

MOV   A,PORT1

ORL   A,#0F0H

CJNE  A,#0FFH,KEYIN1

MOV   A,R3

RL    A

MOV   R3,A

DJNZ  R0,NLINE1

RET

KEYIN1: LCALL DELAY1

LCALL DELAY1

LCALL DELAY1

LCALL NOPEN

RET

-----按键延时-------------

NOPEN:  MOV   A,PORT1

MOV   R2,A

ORL   A,#0F0H

CJNE  A,#0FFH,NOPEN1

SJMP  NOPEN

NOPEN1: LCALL DELAY1

LCALL DELAY1

RET

----------键盘码转换为按键值-----------------

TRANF:  MOV   B,#0

MOV   A,R2

C1:     RRC   A

JNC   C2 C=0跳C2

INC   B

INC   B

INC   B

INC   B  B=B+4

LJMP  C1

C2:     MOV   A,R2

RR    A

RR    A

RR    A

RR    A

C3:     RRC   A

JNC   C4

INC   B

LJMP  C3

C4:     MOV   A,B  B为按键值

RET

---------按键值散转表-------------------

SING0:

MOV   30H,#00H   30H为TABLE1~11地址计数器

NEXT:   MOV   A,0DH

CJNE  A,#1,NN1

MOV   DPTR,#TABLE1

LJMP  WW

NN1:    CJNE  A,#2,NN2

MOV   DPTR,#TABLE2

LJMP  WW

NN2:    CJNE  A,#3,NN3

MOV   DPTR,#TABLE3

LJMP  WW

NN3:    CJNE  A,#4,NN4

MOV   DPTR,#TABLE4

LJMP  WW

NN4:    CJNE  A,#5,NN5

MOV   DPTR,#TABLE5

LJMP  WW

NN5:    CJNE  A,#6,NN6

MOV   DPTR,#TABLE6

LJMP  WW

NN6:    CJNE  A,#7,NN7

MOV   DPTR,#TABLE7

LJMP  WW

NN7:    CJNE  A,#8,NN8

MOV   DPTR,#TABLE8

LJMP  WW

NN8:    CJNE  A,#9,NN9

MOV   DPTR,#TABLE9

LJMP  WW

NN9:    CJNE  A,#10,NN10

MOV   DPTR,#TABLE10

LJMP  WW

NN10:   CJNE  A,#11,NN11

MOV   DPTR,#TABLE11

LJMP  WW

NN11:   CJNE  A,#12,NN12

MOV   0EH,#0A1H

MOV   0BH,#0

LJMP  NN

NN12:   CJNE  A,#13,NN13

MOV   0EH,#0A3H

MOV   0BH,#0H

LJMP  MAIN

NN13:   CJNE  A,#14,NN14

MOV   0EH,#0A5H

MOV   0BH,#0H

LJMP  MAIN

NN14:   CJNE  A,#15,NN

MOV   0EH,#0A7H

MOV   0BH,#00H

LJMP  MAIN

--------------------------------

NN:     LCALL RBAY   读内存

NNT:    MOV   A,R6   R6为从内存中读到的数据

LJMP  IIC

-----------奏乐--------------------------------------------

WW:     MOV   A,30H

JZ    WW0

MOVC  A,@A+DPTR

SJMP  IIC

WW0:    MOVC  A,@A+DPTR

MOV   30H,#1

MOV   31H,A

SJMP  WW

IIC:    MOV   R2,A

JZ    ENDF  A=00 结束标志跳ENDF程序重新开始

ANL   A,#0FH  低4位为延时值

MOV   R5,A   R5延时值频率延时(DELAY)程序用

MOV   A,R2

SWAP  A

ANL   A,#0FH  高4位为音调序号若

JNZ   SING   为0则

CLR   TR1   为休止符

SJMP  DLY1

SING:   DEC   A    频率表从0位置开始,音调序号表从1位置开始,0位置数据是解密数据

PUSH  ACC

MOV   A,0DH

CJNE  A,#11,BD  若>11(B)键,即为C~F键转BD0若<=11(B)键转DE,音调序号+31H

POP   ACC

SJMP  DE

BD:     POP   ACC

JNC   BD0

DE:     ADD   A,31H

BD0:    MOV   22H,A

RL    A

MOV   DPTR,#TABLE

MOVC  A,@A+DPTR

MOV   TH1,A

MOV   21H,A

MOV   A,22H

RL    A

INC   A

MOVC  A,@A+DPTR

MOV   TL1,A

MOV   20H,A

SETB  TR1

DLY1:   INC   R5

ACALL DELAY

INC   30H

INC   0BH

MOV   A,0DH    取按键值判断是读内存键还是读乐谱序号键

CJNE  A,#0BH,NNBD  若按键值<11取下1个乐谱若按键值为12~15(C~F)转NNBD读内存

NEXT1:  LJMP  NEXT

NNBD:   JC    NEXT1

LJMP  NN   读内存

--------程序重新开始---------------------------------------

ENDF:   CLR   TR1

LJMP  MAIN

--------T0中断服务d奏频率延迟时间---------------------------------------------

TIME0:  INC   0AH    d奏乐谱频率延迟值

MOV   TH0,#0C2H

MOV   TL0,#0F6H    定时初值 =49910    计数次数为 2^16(65536)-49910=15626=16ms

RETI

--------T1中断服务发声-----------------------

TIME1:  PUSH  ACC

PUSH  PSW

MOV   TL1,20H

MOV   TH1,21H

CPL   P3.7

POP   PSW

POP   ACC

RETI

--------读数据--------------------

RBAY:   LCALL START

MOV   A,#0A0H

LCALL WRBYT

LCALL TACK

MOV   A,0BH

LCALL WRBYT

LCALL TACK

LCALL START

MOV   A,0EH

LCALL WRBYT

LCALL TACK

LCALL RDBYT

LCALL NOTACK

LCALL STOP

RET

-------写数据-------------------

WBAY:   LCALL START

MOV   A,#0A0H

LCALL WRBYT

LCALL TACK

MOV   A,0BH

LCALL WRBYT

LCALL TACK

MOV   A,0CH

LCALL WRBYT

LCALL TACK

LCALL STOP

RET

---------写数据---------------

WKX03:  MOV   R1,#10H

LCALL START

MOV   A,#0A2H

LCALL WRBYT

LCALL TACK

MOV   A,0CH

LCALL WRBYT

LCALL TACK

MOV   R0,#4

WKX031: MOV   A,@R1

LCALL WRBYT

LCALL TACK

INC   R1

DJNZ  R0,WKX031

LCALL STOP

LCALL DELAY1

LCALL DELAY1

RET

-------启动24C16读写时序------------------

START:  SETB  SDA

NOP

NOP

NOP

NOP

SETB  SCK

NOP

NOP

NOP

NOP

CLR   SDA

NOP

NOP

NOP

NOP

CLR   SCK

NOP

NOP

NOP

NOP

RET

-------停止信号------------------

STOP:   CLR   SDA

NOP

NOP

NOP

NOP

SETB  SCK

NOP

NOP

NOP

NOP

SETB  SDA

NOP

NOP

NOP

NOP

CLR   SCK

NOP

NOP

NOP

NOP

RET

-------应答信号-----------------

TACK: SETB  SDA

CLR   SDA

NOP

NOP

NOP

NOP

SETB  SCK

NOP

NOP

NOP

NOP

CLR   SCK

NOP

NOP

NOP

NOP

SETB  SDA

NOP

NOP

NOP

NOP

RET

-------------------------

CHACK:  SETB  SDA

NOP

NOP

NOP

NOP

SETB  SCK

NOP

NOP

NOP

NOP

MOV   C,SDA

CLR   SCK

NOP

NOP

NOP

NOP

RET

-----------------------------

NOTACK: NOP

SETB  SDA

NOP

NOP

NOP

NOP

SETB  SCK

NOP

NOP

NOP

NOP

CLR   SCK

NOP

NOP

NOP

NOP

RET

------读IIC-24C16------------------

RDBYT:  MOV   R7,#8

SETB  SDA

NOP

NOP

NOP

NOP

RDBYT1: SETB  SCK

NOP

NOP

NOP

NOP

NOP

NOP

MOV   C,SDA

MOV   A,R6

RLC   A

MOV   R6,A

CLR   SCK

NOP

NOP

NOP

NOP

NOP

NOP

DJNZ  R7,RDBYT1

RET

------写IIC-24C16---------------

WRBYT:  MOV   R7,#8

WRBYT1: RLC   A

MOV   SDA,C

JC    WRBYT2

CLR   SDA

NOP

NOP

NOP

NOP

SETB  SCK

NOP

NOP

NOP

NOP

NOP

NOP

CLR   SCK

NOP

NOP

NOP

NOP

NOP

NOP

DJNZ  R7,WRBYT1

RET

WRBYT2: SETB  SDA

NOP

NOP

NOP

NOP

SETB  SCK

NOP

NOP

NOP

NOP

CLR   SCK

NOP

NOP

NOP

NOP

CLR   SDA

NOP

NOP

NOP

NOP

DJNZ  R7,WRBYT1

RET

-------TABLE为频率值  -------------------------------------

TABLE:  DW 0F88CH,0F95BH,0FA15H,0FA67H,0FB04H,0FB90H,0FC0CH 低音1~7

DW 0FC44H,0FCACH,0FD09H,0FD34H,0FD82H,0FDC8H,0FE06H 中音1~7

DW 0FE22H,0FE56H,0FE85H,0FE9AH,0FEC1H,0FEE4H,0FF03H 高音1~7

--------TABLE1~11为音调序号和音调延时表调数据高4位是-----------------------------------

--------音调序号低4位是音调延时值-----------------------------------------------------------------

--------兰花草---------------------------------------

TABLE1: DB 02H,42H,82H,82H,82H,84H,02H,72H,62H,72H,62H

DB 52H,48H,0B2H,0B2H,0B2H,0B2H,0B4H,02H,0A2H

DB 12H,0A2H,0D2H,92H,88H,82H,0B2H,0B2H,0A2H,84H

DB 02H,72H,62H,72H,62H,52H,44H,02H,12H,12H,62H

DB 62H,52H,44H,02H,82H,72H,62H,52H,32H,48H,00

-------哈巴--------------------------------------------

TABLE2: DB 04H,42H,42H,42H,52H,64H,04H,62H,62H,62H,72H,84H,04H

DB 92H,92H,82H,72H,64H,04H,82H,82H,52H,62H,44H,04H

DB 42H,42H,42H,52H,64H,04H,62H,62H,62H,72H,84H,04H

DB 92H,92H,82H,72H,64H,04H,82H,82H,52H,62H,44H,04H,00H

-------生日快乐---------------------------------------

TABLE3: DB 04H,82H,01H,81H,94H,84H,0B4H,0A4H,04H

DB 82H,01H,81H,94H,84H,0C4H,0B4H,04H

DB 82H,01H,0F4H,0D4H,0B4H,0A4H,94H

DB 0E2H,01H,0E1H,0D4H,0B4H,0C4H,0B4H,04H,00H

-------不倒翁--------------------------------------------

TABLE4: DB 04H,84H,94H,88H,64H,54H,68H,84H,64H

DB 54H,44H,62H,82H,42H,62H,58H1

DB 84H,94H,88H,64H,54H,68H,84H,64H2

DB 54H,44H,52H,42H,52H,62H,48H,00

-------妹妹背着洋娃娃---------------------------------------

TABLE5: DB 04H,84H,02H,82H,64H,54H,64H,54H,48H,64H

DB 02H,52H,44H,24H,14H,24H,18H1

DB 24H,02H,22H,42H,24H,44H,54H,68H,54H2

DB 02H,52H,84H,84H,54H,64H,48H,00

-------两只老虎-------------------------------------------------

TABLE6: DB 04H,44H,54H,64H,44H,44H,54H,64H,44H,64H,74H,88H,64H,74H,88H1

DB 82H,92H,82H,72H,64H,44H,82H,92H,82H

DB 72H,64H,44H,44H,84H,48H,44H,14H,48H,00

-------三只小猫----------------------------------------------

TABLE7: DB 04H,62H,82H,82H,62H,98H,92H,0B2H,0B2H,82H,98H

DB 2H,82H,82H,52H,68H,92H,0B2H,0B2H,82H,98H

DB 62H,82H,82H,62H,92H,92H,94H

DB 92H,0B2H,0B2H,92H,84H,94H,0B8H,0B4H,04H,00

-------绿-------------------------------------------------------

TABLE8: DB 02H,42H,82H,82H,82H,84H,02H,72H,62H,72H,62H,52H,48H

DB 0B2H,0B2H,0B2H,0B2H,0B4H,02H,0A2H

DB 12H,0A2H,0D2H,92H,88H,82H,0B2H,0B2H,0A2H,84H

DB 02H,72H,62H,72H,62H,52H,44H,02H,12H

DB 12H,62H,62H,52H,44H,02H,82H,72H,62H,52H,32H,48H,00

-------绿岛小夜曲-----------------------------------------------

TABLE9: DB 00H,0C2H,0D2H,0F2H,0D2H,0C4H,0D2H,0F2H

DB 0D2H,0C2H,0A2H,92H,0A8H

DB 92H,0A2H,0C2H,0A2H,92H,82H,62H,82H,58H,58H

DB 0C4H,22H,0D2H,0C4H,0A4H,92H,0A2H,92H,82H,92H,0A4H,092H

DB 84H,82H,32H,54H,22H,62H,052H,058H

DB 64H,22H,52H,64H,84H,92H,0A2H,92H,82H,92H,0A4H,0C2H

DB 92H,94H,0A2H,0C4H,22H,0D2H,0C8H,0C8H

DB 0D2H,0D4H,0C2H,0A2H,0A2H,92H,82H,92H,0A2H,0C2H,0A8H

DB 92H,94H,82H,62H,52H,52H,82H,98H,98H

DB 0A2H,0A4H,92H,0A2H,0C2H,0A4H,92H,0A2H,92H,82H,68H

DB 52H,0C2H,0A2H,0F2H,0C2H,0D2H,0A2H,92H,88H,88H

DB 0D2H,0D2H,0D2H,0C2H,0A2H,0A2H,22H

DB 92H,94H,82H,62H,52H,62H,82H,98H,98H

DB 0C2H,0D2H,0C2H,92H,0A2H,0A4H,0A2H

DB 92H,94H,82H,64H,84H,0C8H,0D1H,0C1H,0A2H,0C2H,0D4H,0D2H,0E2H

DB 0C2H,0D2H,0C2H,0A2H,98H

DB 0A4H,92H,82H,64H,22H,82H,92H,0A1H,91H,82H,92H,0A4H,22H,0C2H

DB 0D4H,22H,0A2H,94H,0A2H,92H,88H,88H,00

---------------------------------------------------------------------------

TABLE10:DB 00H,04H,42H,52H,62H,42H,42H,52H,62H,42H,62H,72H,86H,62H,72H,86H1

DB 82H,92H,82H,72H,62H,42H,82H,92H,82H

DB 72H,62H,42H,42H,82H,46H,42H,12H,48H,00

----------------------------------------------------------------------------

TABLE11:DB 00H,23H,01H,63H,01H,51H,61H,41H,51H

DB 64H,22H,92H,51H,61H,72H,64H

DB 04H,63H,01H,93H,01H,81H,91H,0A1H,0A1H

DB 94H,53H,61H,41H,51H,41H,31H,24H,04H

DB 53H,61H,41H,51H,41H,31H,24H,04H,53H,61H,82H

DB 92H,0AAH,02H,93H,0A1H,91H,81H,98H,04H,91H

DB 81H,92H,04H,61H,51H,62H,04H,56H,42H,12H

DB 22H,32H,32,28H,08H,00

--------------------------------------------------------------------------

TABLE12:

DB 01H,00H

---------------------

END

快速傅里叶变换 要用C++ 才行吧 你可以用MATLAB来实现更方便点啊

此FFT 是用VC6.0编写,由FFT.CPP;STDAFX.H和STDAFX.CPP三个文件组成,编译成功。程序可以用文件输入和输出为文件。文件格式为TXT文件。测试结果如下:

输入文件:8.TXT 或手动输入

8 //N

1

2

3

4

5

6

7

8

输出结果为:或保存为TXT文件。(8OUT.TXT)

8

(36,0)

(-4,9.65685)

(-4,4)

(-4,1.65685)

(-4,0)

(-4,-1.65685)

(-4,-4)

(-4,-9.65685)

下面为FFT.CPP文件:

// FFT.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"

#include <iostream>

#include <complex>

#include <bitset>

#include <vector>

#include <conio.h>

#include <string>

#include <fstream>

using namespace std

bool inputData(unsigned long &, vector<complex<double>>&) //手工输入数据

void FFT(unsigned long &, vector<complex<double>>&) //FFT变换

void display(unsigned long &, vector<complex<double>>&) //显示结果

bool readDataFromFile(unsigned long &, vector<complex<double>>&) //从文件中读取数据

bool saveResultToFile(unsigned long &, vector<complex<double>>&) //保存结果至文件中

const double PI = 3.1415926

int _tmain(int argc, _TCHAR* argv[])

{

vector<complex<double>>vecList //有限长序列

unsigned long ulN = 0 //N

char chChoose = ' ' //功能选择

//功能循环

while(chChoose != 'Q' &&chChoose != 'q')

{

//显示选择项

cout <<"\nPlease chose a function" <<endl

cout <<"\t1.Input data manually, press 'M':" <<endl

cout <<"\t2.Read data from file, press 'F':" <<endl

cout <<"\t3.Quit, press 'Q'" <<endl

cout <<"Please chose:"

//输入选择

chChoose = getch()

//判断

switch(chChoose)

{

case 'm': //手工输入数据

case 'M':

if(inputData(ulN, vecList))

{

FFT(ulN, vecList)

display(ulN, vecList)

saveResultToFile(ulN, vecList)

}

break

case 'f'://从文档读取数据

case 'F':

if(readDataFromFile(ulN, vecList))

{

FFT(ulN, vecList)

display(ulN, vecList)

saveResultToFile(ulN, vecList)

}

break

}

}

return 0

}

bool Is2Power(unsigned long ul) //判断是否是2的整数次幂

{

if(ul <2)

return false

while( ul >1 )

{

if( ul % 2 )

return false

ul /= 2

}

return true

}

bool inputData(unsigned long &ulN, vector<complex<double>>&vecList)

{

//题目

cout<<"\n\n\n==============================Input Data===============================" <<endl

//输入N

cout<<"\nInput N:"

cin>>ulN

if(!Is2Power(ulN)) //验证N的有效性

{

cout<<"N is invalid (N must like 2, 4, 8, .....), please retry." <<endl

return false

}

//输入各元素

vecList.clear() //清空原有序列

complex<double>c

for(unsigned long i = 0i <ulNi++)

{

cout <<"Input x(" <<i <<"):"

cin >> c

vecList.push_back(c)

}

return true

}

bool readDataFromFile(unsigned long &ulN, vector<complex<double>>&vecList) //从文件中读取数据

{

//题目

cout<<"\n\n\n===============Read Data From File==============" <<endl

//输入文件名

string strfilename

cout <<"Input filename:"

cin >>strfilename

//打开文件

cout <<"open file " <<strfilename <<"......." <<endl

ifstream loadfile

loadfile.open(strfilename.c_str())

if(!loadfile)

{

cout <<"\tfailed" <<endl

return false

}

else

{

cout <<"\tsucceed" <<endl

}

vecList.clear()

//读取N

loadfile >>ulN

if(!loadfile)

{

cout <<"can't get N" <<endl

return false

}

else

{

cout <<"N = " <<ulN <<endl

}

//读取元素

complex<double>c

for(unsigned long i = 0i <ulNi++)

{

loadfile >>c

if(!loadfile)

{

cout <<"can't get enough infomation" <<endl

return false

}

else

cout <<"x(" <<i <<") = " <<c <<endl

vecList.push_back(c)

}

//关闭文件

loadfile.close()

return true

}

bool saveResultToFile(unsigned long &ulN, vector<complex<double>>&vecList) //保存结果至文件中

{

//询问是否需要将结果保存至文件

char chChoose = ' '

cout <<"Do you want to save the result to file? (y/n):"

chChoose = _getch()

if(chChoose != 'y' &&chChoose != 'Y')

{

return true

}

//输入文件名

string strfilename

cout <<"\nInput file name:"

cin >>strfilename

cout <<"Save result to file " <<strfilename <<"......" <<endl

//打开文件

ofstream savefile(strfilename.c_str())

if(!savefile)

{

cout <<"can't open file" <<endl

return false

}

//写入N

savefile <<ulN <<endl

//写入元素

for(vector<complex<double>>::iterator i = vecList.begin()i <vecList.end()i++)

{

savefile <<*i <<endl

}

//写入完毕

cout <<"save succeed." <<endl

//关闭文件

savefile.close()

return true

}

void FFT(unsigned long &ulN, vector<complex<double>>&vecList)

{

//得到幂数

unsigned long ulPower = 0 //幂数

unsigned long ulN1 = ulN - 1

while(ulN1 >0)

{

ulPower++

ulN1 /= 2

}

//反序

bitset<sizeof(unsigned long) * 8>bsIndex //二进制容器

unsigned long ulIndex//反转后的序号

unsigned long ulK

for(unsigned long p = 0p <ulNp++)

{

ulIndex = 0

ulK = 1

bsIndex = bitset<sizeof(unsigned long) * 8>(p)

for(unsigned long j = 0j <ulPowerj++)

{

ulIndex += bsIndex.test(ulPower - j - 1) ? ulK : 0

ulK *= 2

}

if(ulIndex >p)

{

complex<double>c = vecList[p]

vecList[p] = vecList[ulIndex]

vecList[ulIndex] = c

}

}

//计算旋转因子

vector<complex<double>>vecW

for(unsigned long i = 0i <ulN / 2i++)

{

vecW.push_back(complex<double>(cos(2 * i * PI / ulN) , -1 * sin(2 * i * PI / ulN)))

}

for(unsigned long m = 0m <ulN / 2m++)

{

cout<<"\nvW[" <<m <<"]=" <<vecW[m]

}

//计算FFT

unsigned long ulGroupLength = 1 //段的长度

unsigned long ulHalfLength = 0 //段长度的一半

unsigned long ulGroupCount = 0//段的数量

complex<double>cw //WH(x)

complex<double>c1 //G(x) + WH(x)

complex<double>c2 //G(x) - WH(x)

for(unsigned long b = 0b <ulPowerb++)

{

ulHalfLength = ulGroupLength

ulGroupLength *= 2

for(unsigned long j = 0j <ulNj += ulGroupLength)

{

for(unsigned long k = 0k <ulHalfLengthk++)

{

cw = vecW[k * ulN / ulGroupLength] * vecList[j + k + ulHalfLength]

c1 = vecList[j + k] + cw

c2 = vecList[j + k] - cw

vecList[j + k] = c1

vecList[j + k + ulHalfLength] = c2

}

}

}

}

void display(unsigned long &ulN, vector<complex<double>>&vecList)

{

cout <<"\n\n===========================Display The Result=========================" <<endl

for(unsigned long d = 0d <ulNd++)

{

cout <<"X(" <<d <<")\t\t\t = " <<vecList[d] <<endl

}

}

下面为STDAFX.H文件:

// stdafx.h : 标准系统包含文件的包含文件,

// 或是常用但不常更改的项目特定的包含文件

#pragma once

#include <iostream>

#include <tchar.h>

// TODO: 在此处引用程序要求的附加头文件

下面为STDAFX.CPP文件:

// stdafx.cpp : 只包括标准包含文件的源文件

// FFT.pch 将成为预编译头

// stdafx.obj 将包含预编译类型信息

#include "stdafx.h"

// TODO: 在 STDAFX.H 中

//引用任何所需的附加头文件,而不是在此文件中引用

#include "stdafx.h"

#include <iostream>

using namespace std

NN(int)

int main(int argc, char* argv[])

{

int i

cout<<"请输入1-9之间的一个整数:"

cin>>i

cout<<endl

NN(i)

return 0

}

int NN(int x)

{

    for(int i=1i<x+1i++)

{

   for(int j=1j<i+1j++)

   {

       cout<<j<<"*"<<i<<"="<<j*i<<" "

   }

   cout<<endl

}

}


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/12138610.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存