GNU ARM汇编--(九)s3c2440的PWM

RT-Thread移植NUC980实战:从BSP适配到驱动调试全解析 实时操作系统(RTOS)是嵌入式开发中平衡资源、性能与实时性的关键技术,其核心在于提供确定性的任务调度与中断响应。RT-Thread作为一款国产开源RTOS,以其组件化、高实时性及对POSIX标准的支持,在工控、物联网网关等场景中广泛应用。其技术价值在于为资源受限的ARM9等微控制器提供了类似Linux的丰富生态与开发体验,同时保证了硬实时性能。在具体工程实践中,将RT-Thread移植到新唐NUC980这类高性能工控芯片上,涉及BSP(板级支持包)创建、时钟树配置、内存映射修改等关键步骤。例如,通过借鉴N 阅读详情
依旧从datasheet开始看起,锻炼下阅读英文技术手册的能力

PWM TIMER
概述
    s3c2440有5个16bit的定时器.Timer0,1,2和3有PWM功能.Timer4是没有输出管脚的内部定时器.Timer0有一个dead-zone产生器,用于大电流设备.
    Timer0和1共用一个8bit的预分频器,而timer2,3,4共用另外一个8bit的预分频器.每一个定时器都有一个时钟除法器,可以产生5个不同的除法信号(1/2,1/4,1/8,1/16和TCLK).每一个定时器从时钟除法器接收各自的时钟信号,除法器从各自的8bit预分频器接收时钟.8bit的预分频器是可编程控制的,将PCLK除成要加载的值,存在TCFG0和TCFG1中.
    当定时器启用时定时器计数缓冲寄存器(TCNTBn)将初始值加载到down-counter中.定时器比较缓冲寄存器(TCMPBn)将初始值加载到比较寄存器中与donw-counter的值比较.当频率变化时TCNTBn和TCMPBn的双缓冲属性保证定时器产生稳定的输出.
    每个定时器有自己的16bit down-counter,由定时器时钟驱动.当down-counter为0,定时器中断请求产生来通知CPU定时器操作以及完成了.当定时器的计数器为0,相关的TCNTBn的值会自动的加载到down-counter中来继续下一次操作.然而,当定时器停止,比如在定时器运行中清除TCONn的定时器使能位,TCNTBn不会重加载到计数器中.
    TCMPBn的值被用于PWM.当down-counter的值与比较寄存器的值吻合时,定时器控制逻辑会改变输出电平.所以比较寄存器决定PWM输出的打开时间.


属性
    5个16bit的定时器
    两个8bit的预分频器&两个4bit的除法器
    输出波形可编程控制
    自动重加载模式或one-shot pulse mode
    dead-zone产生器


PWM TIMER OPERATION
Prescaler&Divider


BASIC TIMER OPERATION
    一个定时器(除了5)有TCNTBn,TCNTn,TCMPBn和TCMPn.当定时器为0时TCNTBn和TCMPBn加载到TCNTn和TCMPn中.当TCNTn为0,如果中断开启的话就会产生一个中断请求.
    
AUTO RELOAD&DOUBLE BUFFERING
    PWM定时器有一个双缓冲功能,保证下次定时器操作时重加载的值改变时无需停止当前的定时器操作.所以新的定时器的值设定,当前的定时器操作也可以成功完成.
    定时器的值可以写到TCNTBn中,定时器的当前计数值可以从TCNTOn中读到.TCNTBn被读取的值,不表明计数器的当前状态,而是下一次定时器持续期间的重加载值.
    当TCNTn为0,自动重加载操作会复制TCNTBn到TCNTn中.如果TCNTn为0,而自动重加载的使能位为0,那么TCNTn不会再操作了.


TIMER INITIALIZATION USING MANUAL UPDATE BIT AND INVERTER BIT
    当down-counter为0,定时器的自动重加载操作就会动作.所以user要预先定义TCNTn的初始值.在这种情况下,初始值通过手动更新位进行加载.下面的步骤描述如何启动一个定时器:
    1.向TCNTBn和TCMPBn中些初始值
    2.设置定时器的手动更新位.推荐配置inverter on/off bit(不管用不用)
    3.设置定时器的开始位来启动定时器(同时清除手动更新位)
    如果定时器被强行停止,TCNTn保持计数器的值而且不会从TCNTBm中重加载.如果要设置一个新值,要执行手动更新.
    注意:不论何时TOUT inverter on/off bit被更改,在定时器运行时TOUTn的逻辑值都会改变.因此,最好在配置手动更新位的时候配置inverter on/off bit.
    TIMER OPERATION

上面的图是下面操作的结果:

1.使能自动重加载功能.设置TCNTBn为160(50+110),TCMPBn为110.设置手动更新位并配置反转位(on/off).手动更新位将TCNTn和TCMPn的值更新到TCNTBn和TCMPBn中.   接下来设置TCNTBn为80(40+40),TCMPBn为40,它们决定下一次重加载的值.

2.设置开始位,手动更新位设为0.关闭反转器,打开自动重加载.在等待时间后定时器开始计数

3.当TCNTn和TCMPn有相同的值时,TOUTn的逻辑电平由低变为高

4.当TCNTn为0时,中断请求产生,TCNTBn的值被加载到一个临时寄存器.在下次定时器周期,TCNTn会重载临时寄存器的值.

5.在中断服务例程中,TCNTBn设为80(20+60),TCMPBn设置为60,同样用于下一次周期.

6.当TCNTn和TCMPn有相同的值时,TOUTn的逻辑电平由低变为高

7.当TCNTn为0,TCNTn自动加载TCNTBn的值,触发中断请求.

8.在中断服务例程中自动重加载和中断请求被禁用,停止定时器

9.当TCNTn与TCMPn有相同值,TOUTn的逻辑电平由低变为高

10.即使TCNT0为0,因为自动重加载被禁用了所以TCNTn不会再重加载,定时器停止了

11.没有中断请求产生了


PULSE WIDTH MODULATION(PWM)

    通过使用TCMPBn来实现PWM功能.PWM的频率由TCNTBn来决定.
    减少TCMPBn的值可以有更高的PWM值.增加TCMPBn的值可以有更低的PWM值.如果输出反转使能了,增加和减少操作也要反转.
    双缓冲功能允许在ISR中将下一次PWM的TCMPBn的值在当前PWM的周期的任何一个时间点被写入.


OUTPUT LEVEL CONTROL

    假定反转功能时关闭的,下面的步骤描述如何保证TOUT是高还是低:
    1.关闭自动重加载位.TOUTn时高电平,当TCNTn为0时定时器停止.
    2.通过清除定时器的开始位来停止定时器.如果TCNTn<=TCMPn,输出高;如果TCNTn>TCMPn,输出低.
    3.可以通过TCON的反转开关来决定TOUT是否反转.反转器会移除额外的电流来适应输出电平.

PWM的各个寄存器描述

(注:因为TQ2440的板子是用TOUT0来控制蜂鸣器的,所以有些寄存器就不关注了)

定时器配置寄存器0(TCFG0)

定时器输入时钟周期 = PCLK/(prescaler + 1)/(divider value)

{prescaler} = 0~255

{divider value} = 2,4,8,16

Register            Address              R/W                           Description

TCFG0          0x51000000           R/W                       配置两个8的预分频器


TCFG0                               Bit                                           Description

Dead zone length             [23:16]                         死区的长度,长度等于timer0的单位长度

Prescaler1                        [15:8]                           这个是给Timer2 3 4用的

Prescaler0                        [7:0]                             这个是给Timer0 1用的


定时器配置寄存器1(TCFG1)

Register            Address                         R/W                                        Description 

TCFG1           0x51000004                     R/W                               5路MUX和DMA模式选择寄存器


TCFG1                  Bit                                       Description                

DMA mode          [23:20]                           选择DMA请求通道

                                                                  0000=No select  0001=Timer0 0010=Timer1  

                                                                  0011=Timer2 0100=Timer3  0101=Timer4 

MUX4                  [19:16]                           为PWM Timer4选择复用输入

                                                                   0000=1/2 0001=1/4 0000=1/8

                                                                   0011=1/16  01xx=External TCLK1

MUX3                  [15:12]                            为PWM Timer3选择复用输入

                                                                    0000=1/2 0001=1/4 0000=1/8

                                                                    0011=1/16  01xx=External TCLK1

MUX2                  [11:8]                              为PWM Timer2选择复用输入

                                                                    0000=1/2 0001=1/4 0000=1/8

                                                                    0011=1/16  01xx=External TCLK1

MUX1                  [7:4]                               为PWM Timer1选择复用输入

                                                                    0000=1/2 0001=1/4 0010=1/8

                                                                    0011=1/16  01xx=External TCLK1

MUX0                  [3:0]                               为PWM Timer0选择复用输入

                                                                    0000=1/2 0001=1/4 0010=1/8

                                                                    0011=1/16  01xx=External TCLK1


Timer控制寄存器     
Register                  Address              R/W                  Description
TCON                     0x51000008        R/W             定时器控制寄存器

TCON                                        Bit                       Descrption         
Dead zone enable                     [4]                      决定死区的操作 0=disable 1=enable
Timer0 auto reload on/off          [3]                      决定Timer0的自动重载 0=one-shot 1=auto reload
Timer0 output inverter on/off     [2]                      决定Timer0的输出电平反转开关0=关闭 1=打开TOUT0的反转
Timer0手动更新(注意)               [1]                      决定Timer0的手动更新位0=不操作  1=更新TCNTB0&TCMPB0
Timer0开始/停止                        [0]                      决定Timer0的开始/关闭0=停止  1=开启
注意:在下次写之前要被清除

Timer0 COUNT BUFFER REGISTER & COMPARE BUFFER REGISTER(TCNTB0/TCMPB0)
Register                      Address                          R/W                                         Description
TCNTB0                     0x5100000c                    R/W                                         Timer0计数缓冲寄存器
TCMPB0                     0x51000010                   R/W                                          Timer0比较缓冲寄存器

TCMPB0                                                  Bit                                              Description
定时器比较缓冲寄存器                            [15:0]                                   为Timer0设置比较缓冲值
TCNTB0                                                   Bit                                              Description
定时器计数缓冲寄存器                            [15:0]                                    为Timer0设置计数缓冲值

Timer0计数观察寄存器(TCNTO0)
Register                          Address                  R/W                                         Description
TCNTO0                         0x51000014             R                                     Timer0计数观察寄存器

按照datasheet的一些说明和步骤,给出汇编代码:
  1. <PRE class=cpp name="code">/* 
  2. copyleft@  dndxhej@gmail.com 
  3. */  
  4.   
  5. .equ   NOINT, 0xc0  
  6.   
  7. .equ    GPBCON, 0x56000010      @led  
  8. .equ    GPBDAT, 0x56000014      @led  
  9. .equ   GPBUP,        0x56000018    @led  
  10. .equ    GPFCON, 0x56000050      @interrupt config  
  11. .equ    EINTMASK, 0x560000a4  
  12. .equ    EXTINT0,  0x56000088  
  13. .equ    EXTINT1,  0x5600008c  
  14. .equ    EXTINT2,  0x56000090  
  15. .equ    INTMSK,  0x4A000008  
  16. .equ   EINTPEND,     0x560000a8  
  17.   
  18. .equ    SUBSRCPND,  0x4a000018   
  19. .equ    INTSUBMSK,  0x4a00001c  
  20.   
  21.   
  22.   
  23. .equ   SRCPND,   0X4A000000  
  24. .equ   INTPND,   0X4A000010  
  25.   
  26.   
  27. .equ    GPHCON, 0x56000070  
  28. .equ    GPHDAT, 0x56000074  
  29.   
  30. .equ GPB5_out,  (1<<(5*2))    
  31. .equ GPB6_out,  (1<<(6*2))    
  32. .equ GPB7_out,  (1<<(7*2))    
  33. .equ GPB8_out,  (1<<(8*2))    
  34.         
  35. .equ GPBVALUE,    (GPB5_out | GPB6_out | GPB7_out | GPB8_out)    
  36.   
  37. .equ    LOCKTIME, 0x4c000000  
  38. .equ    MPLLCON, 0x4c000004  
  39. .equ    UPLLCON, 0x4c000008  
  40. .equ    M_MDIV, 92  
  41. .equ   M_PDIV, 1  
  42. .equ    M_SDIV, 1  
  43. .equ    U_MDIV, 56  
  44. .equ   U_PDIV, 2  
  45. .equ    U_SDIV, 2  
  46.   
  47. .equ    CLKDIVN, 0x4c000014  
  48. .equ    DIVN_UPLL, 0  
  49. .equ    HDIVN,  1  
  50. .equ    PDIVN,  1    @FCLK : HCLK : PCLK = 1:2:4  
  51.   
  52.   
  53. .equ    WTCON,  0x53000000  
  54. .equ    Pre_scaler,  249  
  55. .equ    wd_timer,   1  
  56. .equ    clock_select,   00   @316  
  57. .equ    int_gen,    1     @开中断  
  58. .equ    reset_enable,   0  @关掉重启信号  
  59.   
  60. .equ    WTDAT,0x53000004  
  61. .equ    Count_reload,50000    @定时器定为2S PCLK = 100M   PCLK/(Pre_scaler+1)/clock_select = 100M/(249+1)/16=25k   50000/25k=2s  
  62.   
  63. .equ    WTCNT,0x53000008  
  64. .equ    Count,50000  
  65.   
  66.   
  67. .equ    TCFG0,0x51000000  
  68. .equ    Prescaler1,0x00   @[15:8]Timer234  
  69. .equ    Prescaler0,249   @[7:0]Timer01  
  70.   
  71. .equ    TCFG1,0x51000004  
  72. .equ    DMA_MODE,0x0        @[23:20]no dma channal  
  73. .equ    MUX0,0x2            @[3:0]   1/8  
  74. @定时器输入时钟周期 = PCLK/(prescaler + 1)/(divider value)  
  75. @clk = 100M/(249+1)/8=25k  
  76.   
  77. .equ    TCON,0x51000008  
  78. .equ    DZ_eable,0    @[4]关闭死区的操作  
  79. .equ    auto_reload,1    @[3]auto_reload  
  80. .equ    inverter,1  @[2]打开电平反转  
  81. .equ    man_update,1   @[1]手动更新  
  82. .equ   clear_man_update,0  
  83. .equ    start,1 @[0]开始  
  84. .equ    stop,0      @[0]停止  
  85.   
  86. .equ    TCNTB0,0x5100000c         
  87. .equ    TCMPB0,0x51000010  
  88.   
  89. .equ    TCNTO0,0x51000014  
  90.   
  91.   
  92. .equ    ULCON0, 0x50000000  
  93. .equ    IR_MODE,    0x0   @[6]正常模式  
  94. .equ    Parity_Mode,    0x0 @[5:3]无校验位  
  95. .equ    Num_of_stop_bit,  0x0  @[2]一个停止位  
  96. .equ    Word_length,    0b11    @[1:0]8个数据位  
  97.   
  98. .equ    UCON0,  0x50000004  
  99. .equ    FCLK_Div,   0   @[15:12]  时钟源选择用PCLK,所以这里用默认值  
  100. .equ    Clk_select, 0b00    @[11:10] 时钟源选择使用PCLK  
  101. .equ    Tx_Int_Type, 1  @[9]  中断请求类型为Level  
  102. .equ    Rx_Int_Type, 0 @1  @[8]  中断请求类型为Level  
  103. .equ    Rx_Timeout, 0  @[7]  
  104. .equ    Rx_Error_Stat_Int, 1 @[6]  
  105. .equ    Loopback_Mode, 0 @[5]  正常模式  
  106. .equ    Break_Sig,  0 @[4] 不发送终止信号  
  107. .equ    Tx_Mode,    0b01 @[3:2]  中断请求或轮循模式  
  108. .equ    Rx_Mode,    0b01 @[1:0]  中断请求或轮循模式  
  109.   
  110. .equ    UFCON0, 0x50000008  
  111. .equ    Tx_FIFO_Trig_Level, 0b00 @[7:6]  
  112. .equ    Rx_FIFO_Trig_Level, 0b00 @[5:4]  
  113. .equ    Tx_FIFO_Reset,  0b0 @[2]  
  114. .equ    Rx_FIFO_Reset,  0b0 @[1]  
  115. .equ    FIFO_Enable,    0b0 @[0] 非FIFO模式  
  116.   
  117. .equ    UMCON0, 0x5000000C    @这个寄存器可以不管的  
  118. .equ    UTRSTAT0,   0x50000010  
  119. .equ    UERSTAT0,   0x50000014  
  120. .equ    UFSTAT0,    0x50000018  
  121. .equ    UMSTAT0,    0x5000001C  
  122. .equ    UTXH0,      0x50000020   @(L 小端)  
  123. .equ    URXH0,      0x50000024   @(L 小端)  
  124.   
  125. .equ     UBRDIV0,    0x50000028  
  126. .equ     UBRDIV,    0x35   @PCLK=400M/4=100M   UBRDIV = (int)(100M/115200/16) - 1 = 53 = 0x35  
  127.   
  128. .global Buzzer_Freq_Set  
  129.   
  130. .global _start  
  131. _start:     b   reset  
  132.         ldr     pc, _undefined_instruction  
  133.         ldr     pc, _software_interrupt  
  134.         ldr pc, _prefetch_abort  
  135.         ldr pc, _data_abort  
  136.         ldr pc, _not_used  
  137.         @b  irq  
  138.         ldr     pc, _irq  
  139.         ldr     pc, _fiq  
  140.   
  141.   
  142.   
  143. _undefined_instruction:     .word undefined_instruction  
  144. _software_interrupt:        .word software_interrupt  
  145. _prefetch_abort:        .word prefetch_abort  
  146. _data_abort:            .word data_abort  
  147. _not_used:          .word not_used  
  148. _irq:               .word irq  
  149. _fiq:               .word fiq  
  150.   
  151. .balignl 16,0xdeadbeef  
  152.   
  153. reset:  
  154.   
  155.   
  156.     ldr     r3, =WTCON  
  157.     mov r4, #0x0                       
  158.     str r4, [r3]    @ disable watchdog      
  159.   
  160.     ldr r0, =GPBCON  
  161.     ldr r1, =0x15400     @这个时候暂不配置GPB0为TOUT0,这时候只是配置GPB0为TOUT0  
  162.     str r1, [r0]  
  163.   
  164.     ldr r2, =GPBDAT  
  165.     ldr r1, =0x160  
  166.     str r1, [r2]  
  167.   
  168.     bl clock_setup  
  169.     bl uart_init  
  170.     //bl delay   
  171.   
  172.   
  173.     msr cpsr_c, #0xd2 @进入中断模式  
  174.     ldr sp, =3072 @中断模式的栈指针定义  
  175.   
  176.     msr cpsr_c, #0xd3 @进入系统模式  
  177.     ldr sp, =4096 @设置系统模式的栈指针  
  178.   
  179. @--------------------------------------------  
  180.   
  181.     ldr r0, =GPBUP  
  182.     ldr r1, =0x03f0    
  183.     str r1, [r0]        
  184.      
  185.     ldr r0, =GPFCON  
  186.     ldr r1, =0x2ea@0x2      
  187.     str r1, [r0]    
  188.   
  189.     ldr r0, =EXTINT0  
  190.     @ldr    r1, =0x8f888@0x0@0x8f888      @~(7|(7<<4)|(7<<8)|(7<<16))   //低电平触发中断   
  191.     ldr r1, =0xafaaa@0x0@0x8f888      //下降沿触发中断   
  192.     str r1, [r0]    
  193.   
  194.     ldr r0, =EINTPEND  
  195.     ldr r1, =0xf0@0b10000  
  196.     str r1, [r0]    
  197.   
  198.     ldr r0, =EINTMASK  
  199.     ldr r1, =0x00@0b00000  
  200.     str r1, [r0]    
  201.   
  202.   
  203.   
  204.     ldr r0, =SRCPND  
  205.     ldr r1, =0x3ff@0x1@0b11111  
  206.     str r1, [r0]    
  207.   
  208.     ldr r0, =SUBSRCPND  
  209.     ldr r1, =0x1<<13  
  210.     str r1, [r0]    
  211.   
  212.     ldr r0, =INTPND  
  213.     ldr r1, =0x3ff@0x1@0b11111  
  214.     str r1, [r0]    
  215.   
  216.     ldr r0, =INTSUBMSK  
  217.     ldr r1, =0x0<<13  
  218.     str r1, [r0]    
  219.   
  220.     ldr r0, =INTMSK  
  221.     ldr r1, =0xfffff000@0b00000  
  222.     str r1, [r0]    
  223.   
  224.     MRS r1, cpsr  
  225.     BIC r1, r1, #0x80  
  226.     MSR cpsr_c, r1  
  227.   
  228.   
  229.     bl     main  
  230.   
  231. irq:  
  232.     sub     lr,lr,#4  
  233.     stmfd   sp!,{r0-r12,lr}  
  234.   
  235.   
  236.     bl irq_isr  
  237.     ldmfd  sp!,{r0-r12,pc}^   
  238.   
  239.   
  240. irq_isr:  
  241.   
  242.     ldr r2, =GPBDAT  
  243.     ldr r1, =0x0e0  
  244.     str r1, [r2]  
  245.   
  246.   
  247.          ldr r0,=EINTPEND  
  248.          ldr r1,=0xf0  
  249.          str r1,[r0]   
  250.   
  251.     ldr r0, =SRCPND  
  252.     ldr r1, =0x3ff@0b11111  
  253.     str r1, [r0]    
  254.   
  255.     ldr r0, =SUBSRCPND  
  256.     ldr r1, =0x3ff@0x1<<13  
  257.     str r1, [r0]    
  258.   
  259.     ldr r0, =INTPND  
  260.     ldr r1, =0x3ff@0b11111  
  261.     str r1, [r0]    
  262.   
  263.     mov pc,lr  
  264.   
  265.   
  266. delay:  
  267.       
  268.     ldr r3,=0xffffff  
  269.   
  270. delay1:  
  271.     sub r3,r3,#1  
  272.   
  273.     cmp r3,#0x0  
  274.   
  275.     bne delay1  
  276.   
  277.     mov pc,lr  
  278.   
  279.   
  280. clock_setup:  
  281.   
  282.     ldr r0,=LOCKTIME  
  283.     ldr r1,=0xffffffff  
  284.     str r1, [r0]  
  285.   
  286.     ldr r0,=CLKDIVN  
  287.     ldr r1,=(DIVN_UPLL<<3) | (HDIVN<<1) | (PDIVN<<0)  
  288.     str r1, [r0]  
  289.   
  290.     ldr r0,=UPLLCON  
  291.     ldr r1,=(U_MDIV<<12) | (U_PDIV<<4) | (U_SDIV<<0)   @Fin=12M  UPLL=48M  
  292.     str r1, [r0]  
  293.     nop  
  294.     nop  
  295.     nop  
  296.     nop  
  297.     nop  
  298.     nop  
  299.     nop  
  300.     ldr r0,=MPLLCON  
  301.     ldr r1,=(M_MDIV<<12) | (M_PDIV<<4) | (M_SDIV<<0)    @Fin=12M  FCLK=400M  
  302.     str r1, [r0]  
  303.   
  304.   
  305.   
  306.     mov pc,lr  
  307.   
  308.   
  309. uart_init:  
  310.     ldr r0,=GPHCON  
  311.     ldr r1,=0x2aaaa     @配置GPIO复用规则为串口  
  312.     str r1, [r0]  
  313.   
  314.     ldr r0,=ULCON0  
  315.     ldr r1,=(IR_MODE<<6) | (Parity_Mode<<3) | (Num_of_stop_bit<<2) | (Word_length<<0)    @  
  316.     str r1, [r0]  
  317.   
  318.     ldr r0,=UCON0  
  319.     ldr r1,=(FCLK_Div<<12) | (Clk_select<<10) | (Tx_Int_Type<<9) | (Rx_Int_Type<<8) | (Rx_Timeout<<7) | (Rx_Error_Stat_Int<<6) |(Loopback_Mode<<5) | (Break_Sig<<4) | (Tx_Mode<<2) | (Rx_Mode<<0)  
  320.     str r1, [r0]  
  321.   
  322.     ldr r0,=UFCON0  
  323.     ldr r1,=(Tx_FIFO_Trig_Level<<6) | (Rx_FIFO_Trig_Level<<4) | (Tx_FIFO_Reset<<2) | (Rx_FIFO_Reset<<1) | (FIFO_Enable<<0)    @  
  324.     str r1, [r0]  
  325.   
  326.     ldr r0,=UBRDIV0  
  327.     ldr r1,=(UBRDIV<<0)  
  328.     str r1, [r0]  
  329.   
  330.         mov pc,lr  
  331.   
  332. Buzzer_Freq_Set:  
  333.   
  334.     //ldr   r0, =GPBCON   
  335.     //ldr   r1, =0x15400     @这个时候暂不配置GPB0为TOUT0,这时候只是配置GPB0为TOUT0   
  336.     //str   r1, [r0]   
  337.   
  338.     ldr r2, =GPBDAT  
  339.     ldr r1, =0x1c1  
  340.     str r1, [r2]  
  341.   
  342.     ldr r2, =GPBCON  
  343.     ldr r1,[r2]  
  344.     ldr r1,[r1]  
  345.     //ldr   r1, =0x15400   
  346.     bic r1,r1,#0x3  
  347.     orr r1,r1,#0x2  
  348.     str r1,[r2]  
  349.   
  350.     ldr r2, =GPBDAT  
  351.     ldr r1, =0x1a0  
  352.     str r1, [r2]  
  353.   
  354.     ldr r1,=TCFG0  
  355.     ldr r2,=(Prescaler0<<0)  
  356.     str r2, [r1]  
  357.   
  358.     ldr r1,=TCFG1  
  359.     ldr r2,=(DMA_MODE<<20) | (MUX0<<0)  
  360.     str r2, [r1]  
  361.   
  362. //  ldr r3,[r0]   
  363. //  str r3,[r2]   
  364.   
  365.   
  366.   
  367.     //mov  r2, r0   
  368.   
  369.     ldr r1,=TCNTB0  
  370.     //ldr r2,=200   
  371.     str r0, [r1]  
  372.       
  373.     mov  r0,r0,LSR #2  
  374.   
  375.     ldr r1,=TCMPB0  
  376.     //ldr r2,=50   
  377.     str r0, [r1]  
  378.   
  379.   
  380.   
  381.     ldr r1,=TCON  
  382.     ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (start<<0)  
  383.     str r2, [r1]  
  384.   
  385.     ldr r1,=TCON  
  386.     ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (clear_man_update<<1) | (start<<0)  
  387.     str r2, [r1]  
  388.   
  389.     ldr r2, =GPBDAT  
  390.     ldr r1, =0x1a0  
  391.     str r1, [r2]  
  392.   
  393.     mov pc,lr  
  394.   
  395. main:  
  396.   
  397.     ldr r1,=TCON  
  398.     ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (stop<<0)  
  399.     str r2, [r1]  
  400.   
  401.        ldr lr, =loop                              
  402.                     
  403.     ldr pc, _pwm_uart_test  
  404.   
  405. _pwm_uart_test: .word pwm_uart_test  
  406. loop:  
  407.         b loop                                               @ 死循环  
  408.   
  409.   
  410.   
  411.   
  412.   
  413. undefined_instruction:  
  414.             nop  
  415. software_interrupt:  
  416.             nop  
  417. prefetch_abort:   
  418.             nop  
  419. data_abort:  
  420.             nop  
  421. not_used:  
  422.             nop  
  423. fiq:  
  424.             nop</PRE><BR>  
  425. <PRE></PRE>  
  426. <PRE></PRE>  

  
  1. /* 
  2. copyleft@  dndxhej@gmail.com 
  3. */  
  4.   
  5. .equ   NOINT, 0xc0  
  6.   
  7. .equ    GPBCON, 0x56000010      @led  
  8. .equ    GPBDAT, 0x56000014      @led  
  9. .equ   GPBUP,        0x56000018    @led  
  10. .equ    GPFCON, 0x56000050      @interrupt config  
  11. .equ    EINTMASK, 0x560000a4  
  12. .equ    EXTINT0,  0x56000088  
  13. .equ    EXTINT1,  0x5600008c  
  14. .equ    EXTINT2,  0x56000090  
  15. .equ    INTMSK,  0x4A000008  
  16. .equ   EINTPEND,     0x560000a8  
  17.   
  18. .equ    SUBSRCPND,  0x4a000018   
  19. .equ    INTSUBMSK,  0x4a00001c  
  20.   
  21.   
  22.   
  23. .equ   SRCPND,   0X4A000000  
  24. .equ   INTPND,   0X4A000010  
  25.   
  26.   
  27. .equ    GPHCON, 0x56000070  
  28. .equ    GPHDAT, 0x56000074  
  29.   
  30. .equ GPB5_out,  (1<<(5*2))    
  31. .equ GPB6_out,  (1<<(6*2))    
  32. .equ GPB7_out,  (1<<(7*2))    
  33. .equ GPB8_out,  (1<<(8*2))    
  34.         
  35. .equ GPBVALUE,    (GPB5_out | GPB6_out | GPB7_out | GPB8_out)    
  36.   
  37. .equ    LOCKTIME, 0x4c000000  
  38. .equ    MPLLCON, 0x4c000004  
  39. .equ    UPLLCON, 0x4c000008  
  40. .equ    M_MDIV, 92  
  41. .equ   M_PDIV, 1  
  42. .equ    M_SDIV, 1  
  43. .equ    U_MDIV, 56  
  44. .equ   U_PDIV, 2  
  45. .equ    U_SDIV, 2  
  46.   
  47. .equ    CLKDIVN, 0x4c000014  
  48. .equ    DIVN_UPLL, 0  
  49. .equ    HDIVN,  1  
  50. .equ    PDIVN,  1    @FCLK : HCLK : PCLK = 1:2:4  
  51.   
  52.   
  53. .equ    WTCON,  0x53000000  
  54. .equ    Pre_scaler,  249  
  55. .equ    wd_timer,   1  
  56. .equ    clock_select,   00   @316  
  57. .equ    int_gen,    1     @开中断  
  58. .equ    reset_enable,   0  @关掉重启信号  
  59.   
  60. .equ    WTDAT,0x53000004  
  61. .equ    Count_reload,50000    @定时器定为2S PCLK = 100M   PCLK/(Pre_scaler+1)/clock_select = 100M/(249+1)/16=25k   50000/25k=2s  
  62.   
  63. .equ    WTCNT,0x53000008  
  64. .equ    Count,50000  
  65.   
  66.   
  67. .equ    TCFG0,0x51000000  
  68. .equ    Prescaler1,0x00   @[15:8]Timer234  
  69. .equ    Prescaler0,249   @[7:0]Timer01  
  70.   
  71. .equ    TCFG1,0x51000004  
  72. .equ    DMA_MODE,0x0        @[23:20]no dma channal  
  73. .equ    MUX0,0x2            @[3:0]   1/8  
  74. @定时器输入时钟周期 = PCLK/(prescaler + 1)/(divider value)  
  75. @clk = 100M/(249+1)/8=25k  
  76.   
  77. .equ    TCON,0x51000008  
  78. .equ    DZ_eable,0    @[4]关闭死区的操作  
  79. .equ    auto_reload,1    @[3]auto_reload  
  80. .equ    inverter,1  @[2]打开电平反转  
  81. .equ    man_update,1   @[1]手动更新  
  82. .equ   clear_man_update,0  
  83. .equ    start,1 @[0]开始  
  84. .equ    stop,0      @[0]停止  
  85.   
  86. .equ    TCNTB0,0x5100000c         
  87. .equ    TCMPB0,0x51000010  
  88.   
  89. .equ    TCNTO0,0x51000014  
  90.   
  91.   
  92. .equ    ULCON0, 0x50000000  
  93. .equ    IR_MODE,    0x0   @[6]正常模式  
  94. .equ    Parity_Mode,    0x0 @[5:3]无校验位  
  95. .equ    Num_of_stop_bit,  0x0  @[2]一个停止位  
  96. .equ    Word_length,    0b11    @[1:0]8个数据位  
  97.   
  98. .equ    UCON0,  0x50000004  
  99. .equ    FCLK_Div,   0   @[15:12]  时钟源选择用PCLK,所以这里用默认值  
  100. .equ    Clk_select, 0b00    @[11:10] 时钟源选择使用PCLK  
  101. .equ    Tx_Int_Type, 1  @[9]  中断请求类型为Level  
  102. .equ    Rx_Int_Type, 0 @1  @[8]  中断请求类型为Level  
  103. .equ    Rx_Timeout, 0  @[7]  
  104. .equ    Rx_Error_Stat_Int, 1 @[6]  
  105. .equ    Loopback_Mode, 0 @[5]  正常模式  
  106. .equ    Break_Sig,  0 @[4] 不发送终止信号  
  107. .equ    Tx_Mode,    0b01 @[3:2]  中断请求或轮循模式  
  108. .equ    Rx_Mode,    0b01 @[1:0]  中断请求或轮循模式  
  109.   
  110. .equ    UFCON0, 0x50000008  
  111. .equ    Tx_FIFO_Trig_Level, 0b00 @[7:6]  
  112. .equ    Rx_FIFO_Trig_Level, 0b00 @[5:4]  
  113. .equ    Tx_FIFO_Reset,  0b0 @[2]  
  114. .equ    Rx_FIFO_Reset,  0b0 @[1]  
  115. .equ    FIFO_Enable,    0b0 @[0] 非FIFO模式  
  116.   
  117. .equ    UMCON0, 0x5000000C    @这个寄存器可以不管的  
  118. .equ    UTRSTAT0,   0x50000010  
  119. .equ    UERSTAT0,   0x50000014  
  120. .equ    UFSTAT0,    0x50000018  
  121. .equ    UMSTAT0,    0x5000001C  
  122. .equ    UTXH0,      0x50000020   @(L 小端)  
  123. .equ    URXH0,      0x50000024   @(L 小端)  
  124.   
  125. .equ     UBRDIV0,    0x50000028  
  126. .equ     UBRDIV,    0x35   @PCLK=400M/4=100M   UBRDIV = (int)(100M/115200/16) - 1 = 53 = 0x35  
  127.   
  128. .global Buzzer_Freq_Set  
  129.   
  130. .global _start  
  131. _start:     b   reset  
  132.         ldr     pc, _undefined_instruction  
  133.         ldr     pc, _software_interrupt  
  134.         ldr pc, _prefetch_abort  
  135.         ldr pc, _data_abort  
  136.         ldr pc, _not_used  
  137.         @b  irq  
  138.         ldr     pc, _irq  
  139.         ldr     pc, _fiq  
  140.   
  141.   
  142.   
  143. _undefined_instruction:     .word undefined_instruction  
  144. _software_interrupt:        .word software_interrupt  
  145. _prefetch_abort:        .word prefetch_abort  
  146. _data_abort:            .word data_abort  
  147. _not_used:          .word not_used  
  148. _irq:               .word irq  
  149. _fiq:               .word fiq  
  150.   
  151. .balignl 16,0xdeadbeef  
  152.   
  153. reset:  
  154.   
  155.   
  156.     ldr     r3, =WTCON  
  157.     mov r4, #0x0                       
  158.     str r4, [r3]    @ disable watchdog      
  159.   
  160.     ldr r0, =GPBCON  
  161.     ldr r1, =0x15400     @这个时候暂不配置GPB0为TOUT0,这时候只是配置GPB0为TOUT0  
  162.     str r1, [r0]  
  163.   
  164.     ldr r2, =GPBDAT  
  165.     ldr r1, =0x160  
  166.     str r1, [r2]  
  167.   
  168.     bl clock_setup  
  169.     bl uart_init  
  170.     //bl delay   
  171.   
  172.   
  173.     msr cpsr_c, #0xd2 @进入中断模式  
  174.     ldr sp, =3072 @中断模式的栈指针定义  
  175.   
  176.     msr cpsr_c, #0xd3 @进入系统模式  
  177.     ldr sp, =4096 @设置系统模式的栈指针  
  178.   
  179. @--------------------------------------------  
  180.   
  181.     ldr r0, =GPBUP  
  182.     ldr r1, =0x03f0    
  183.     str r1, [r0]        
  184.      
  185.     ldr r0, =GPFCON  
  186.     ldr r1, =0x2ea@0x2      
  187.     str r1, [r0]    
  188.   
  189.     ldr r0, =EXTINT0  
  190.     @ldr    r1, =0x8f888@0x0@0x8f888      @~(7|(7<<4)|(7<<8)|(7<<16))   //低电平触发中断   
  191.     ldr r1, =0xafaaa@0x0@0x8f888      //下降沿触发中断   
  192.     str r1, [r0]    
  193.   
  194.     ldr r0, =EINTPEND  
  195.     ldr r1, =0xf0@0b10000  
  196.     str r1, [r0]    
  197.   
  198.     ldr r0, =EINTMASK  
  199.     ldr r1, =0x00@0b00000  
  200.     str r1, [r0]    
  201.   
  202.   
  203.   
  204.     ldr r0, =SRCPND  
  205.     ldr r1, =0x3ff@0x1@0b11111  
  206.     str r1, [r0]    
  207.   
  208.     ldr r0, =SUBSRCPND  
  209.     ldr r1, =0x1<<13  
  210.     str r1, [r0]    
  211.   
  212.     ldr r0, =INTPND  
  213.     ldr r1, =0x3ff@0x1@0b11111  
  214.     str r1, [r0]    
  215.   
  216.     ldr r0, =INTSUBMSK  
  217.     ldr r1, =0x0<<13  
  218.     str r1, [r0]    
  219.   
  220.     ldr r0, =INTMSK  
  221.     ldr r1, =0xfffff000@0b00000  
  222.     str r1, [r0]    
  223.   
  224.     MRS r1, cpsr  
  225.     BIC r1, r1, #0x80  
  226.     MSR cpsr_c, r1  
  227.   
  228.   
  229.     bl     main  
  230.   
  231. irq:  
  232.     sub     lr,lr,#4  
  233.     stmfd   sp!,{r0-r12,lr}  
  234.   
  235.   
  236.     bl irq_isr  
  237.     ldmfd  sp!,{r0-r12,pc}^   
  238.   
  239.   
  240. irq_isr:  
  241.   
  242.     ldr r2, =GPBDAT  
  243.     ldr r1, =0x0e0  
  244.     str r1, [r2]  
  245.   
  246.   
  247.          ldr r0,=EINTPEND  
  248.          ldr r1,=0xf0  
  249.          str r1,[r0]   
  250.   
  251.     ldr r0, =SRCPND  
  252.     ldr r1, =0x3ff@0b11111  
  253.     str r1, [r0]    
  254.   
  255.     ldr r0, =SUBSRCPND  
  256.     ldr r1, =0x3ff@0x1<<13  
  257.     str r1, [r0]    
  258.   
  259.     ldr r0, =INTPND  
  260.     ldr r1, =0x3ff@0b11111  
  261.     str r1, [r0]    
  262.   
  263.     mov pc,lr  
  264.   
  265.   
  266. delay:  
  267.       
  268.     ldr r3,=0xffffff  
  269.   
  270. delay1:  
  271.     sub r3,r3,#1  
  272.   
  273.     cmp r3,#0x0  
  274.   
  275.     bne delay1  
  276.   
  277.     mov pc,lr  
  278.   
  279.   
  280. clock_setup:  
  281.   
  282.     ldr r0,=LOCKTIME  
  283.     ldr r1,=0xffffffff  
  284.     str r1, [r0]  
  285.   
  286.     ldr r0,=CLKDIVN  
  287.     ldr r1,=(DIVN_UPLL<<3) | (HDIVN<<1) | (PDIVN<<0)  
  288.     str r1, [r0]  
  289.   
  290.     ldr r0,=UPLLCON  
  291.     ldr r1,=(U_MDIV<<12) | (U_PDIV<<4) | (U_SDIV<<0)   @Fin=12M  UPLL=48M  
  292.     str r1, [r0]  
  293.     nop  
  294.     nop  
  295.     nop  
  296.     nop  
  297.     nop  
  298.     nop  
  299.     nop  
  300.     ldr r0,=MPLLCON  
  301.     ldr r1,=(M_MDIV<<12) | (M_PDIV<<4) | (M_SDIV<<0)    @Fin=12M  FCLK=400M  
  302.     str r1, [r0]  
  303.   
  304.   
  305.   
  306.     mov pc,lr  
  307.   
  308.   
  309. uart_init:  
  310.     ldr r0,=GPHCON  
  311.     ldr r1,=0x2aaaa     @配置GPIO复用规则为串口  
  312.     str r1, [r0]  
  313.   
  314.     ldr r0,=ULCON0  
  315.     ldr r1,=(IR_MODE<<6) | (Parity_Mode<<3) | (Num_of_stop_bit<<2) | (Word_length<<0)    @  
  316.     str r1, [r0]  
  317.   
  318.     ldr r0,=UCON0  
  319.     ldr r1,=(FCLK_Div<<12) | (Clk_select<<10) | (Tx_Int_Type<<9) | (Rx_Int_Type<<8) | (Rx_Timeout<<7) | (Rx_Error_Stat_Int<<6) |(Loopback_Mode<<5) | (Break_Sig<<4) | (Tx_Mode<<2) | (Rx_Mode<<0)  
  320.     str r1, [r0]  
  321.   
  322.     ldr r0,=UFCON0  
  323.     ldr r1,=(Tx_FIFO_Trig_Level<<6) | (Rx_FIFO_Trig_Level<<4) | (Tx_FIFO_Reset<<2) | (Rx_FIFO_Reset<<1) | (FIFO_Enable<<0)    @  
  324.     str r1, [r0]  
  325.   
  326.     ldr r0,=UBRDIV0  
  327.     ldr r1,=(UBRDIV<<0)  
  328.     str r1, [r0]  
  329.   
  330.         mov pc,lr  
  331.   
  332. Buzzer_Freq_Set:  
  333.   
  334.     //ldr   r0, =GPBCON   
  335.     //ldr   r1, =0x15400     @这个时候暂不配置GPB0为TOUT0,这时候只是配置GPB0为TOUT0   
  336.     //str   r1, [r0]   
  337.   
  338.     ldr r2, =GPBDAT  
  339.     ldr r1, =0x1c1  
  340.     str r1, [r2]  
  341.   
  342.     ldr r2, =GPBCON  
  343.     ldr r1,[r2]  
  344.     ldr r1,[r1]  
  345.     //ldr   r1, =0x15400   
  346.     bic r1,r1,#0x3  
  347.     orr r1,r1,#0x2  
  348.     str r1,[r2]  
  349.   
  350.     ldr r2, =GPBDAT  
  351.     ldr r1, =0x1a0  
  352.     str r1, [r2]  
  353.   
  354.     ldr r1,=TCFG0  
  355.     ldr r2,=(Prescaler0<<0)  
  356.     str r2, [r1]  
  357.   
  358.     ldr r1,=TCFG1  
  359.     ldr r2,=(DMA_MODE<<20) | (MUX0<<0)  
  360.     str r2, [r1]  
  361.   
  362. //  ldr r3,[r0]   
  363. //  str r3,[r2]   
  364.   
  365.   
  366.   
  367.     //mov  r2, r0   
  368.   
  369.     ldr r1,=TCNTB0  
  370.     //ldr r2,=200   
  371.     str r0, [r1]  
  372.       
  373.     mov  r0,r0,LSR #2  
  374.   
  375.     ldr r1,=TCMPB0  
  376.     //ldr r2,=50   
  377.     str r0, [r1]  
  378.   
  379.   
  380.   
  381.     ldr r1,=TCON  
  382.     ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (start<<0)  
  383.     str r2, [r1]  
  384.   
  385.     ldr r1,=TCON  
  386.     ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (clear_man_update<<1) | (start<<0)  
  387.     str r2, [r1]  
  388.   
  389.     ldr r2, =GPBDAT  
  390.     ldr r1, =0x1a0  
  391.     str r1, [r2]  
  392.   
  393.     mov pc,lr  
  394.   
  395. main:  
  396.   
  397.     ldr r1,=TCON  
  398.     ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (stop<<0)  
  399.     str r2, [r1]  
  400.   
  401.        ldr lr, =loop                              
  402.                     
  403.     ldr pc, _pwm_uart_test  
  404.   
  405. _pwm_uart_test: .word pwm_uart_test  
  406. loop:  
  407.         b loop                                               @ 死循环  
  408.   
  409.   
  410.   
  411.   
  412.   
  413. undefined_instruction:  
  414.             nop  
  415. software_interrupt:  
  416.             nop  
  417. prefetch_abort:   
  418.             nop  
  419. data_abort:  
  420.             nop  
  421. not_used:  
  422.             nop  
  423. fiq:  
  424.             nop  





pwm_uart_test.c内容如下:
  1. #include "pwm_uart_test.h"   
  2. extern void Buzzer_Freq_Set(int freq);  
  3. //extern void Buzzer_Freq_Set( void );   
  4. char uart_GetByte(void)  
  5. {  
  6.         while(!(rUTRSTAT0 & 0x1));   //Wait until THR is empty.   
  7.             return RdURXH0();  
  8. }  
  9.   
  10.   
  11. void uart_GetString(char *pt)  
  12. {  
  13.     while(*pt)  
  14.         uart_GetByte();  
  15. }  
  16.   
  17.   
  18. void uart_SendByte(int data)  
  19. {  
  20.       
  21.         if(data=='\n')  
  22.         {  
  23.             while(!(rUTRSTAT0 & 0x2));  
  24.             WrUTXH0('\r');  
  25.         }  
  26.         while(!(rUTRSTAT0 & 0x2));   //Wait until THR is empty.   
  27.         WrUTXH0(data);  
  28.   
  29. }                 
  30.   
  31. //====================================================================   
  32. void uart_SendString(char *pt)  
  33. {  
  34.     while(*pt)  
  35.            uart_SendByte(*pt++);  
  36. }  
  37.   
  38.   
  39. void uart_test(void)  
  40. {  
  41.       
  42.     char str[20] = "\nhello world\n";  
  43.     int a = 97;  
  44.     //while(1)   
  45.     //  uart_SendByte(a);      
  46.     uart_SendString(str);  
  47.     char s = uart_GetByte();  
  48.     //if(s == 'a')   
  49.     if(s == 97)  
  50.         rGPBDAT = 0x1c0;  
  51.     //uart_SendByte(a);   
  52.     //uart_SendByte(97);   
  53.     //uart_SendByte('a');   
  54.     uart_SendByte((int)s);  
  55.     uart_SendByte((int)'s');  
  56. }  
  57.   
  58. void pwm_uart_test(void)  
  59. {  
  60.     int freq = 10;  
  61.     Buzzer_Freq_Set( freq ) ;  
  62.     //Buzzer_Freq_Set(  ) ;   
  63.   
  64.     uart_SendString("start\n");  
  65. /* 
  66.     int i; 
  67.     for(i=0;i<1000;i++) 
  68.         uart_SendString("wait\n"); 
  69.     while( 1 ) 
  70.     { 
  71.         char key = uart_GetByte(); 
  72.         uart_SendByte(key); 
  73.         if( key == 'a' || key == 'A' ) 
  74.         { 
  75.             if( freq < 2000 )  //lci  20000 
  76.                 freq += 10 ; 
  77.                 uart_SendByte('a'); 
  78.             Buzzer_Freq_Set( freq ) ; 
  79.         } 
  80.  
  81.         if( key == 'b' || key == 'B' ) 
  82.         { 
  83.             if( freq > 11 ) 
  84.                 freq -= 10 ; 
  85.                 uart_SendByte('b'); 
  86.             Buzzer_Freq_Set( freq ) ; 
  87.         } 
  88.          
  89.         //uart_SendString( "\tFreq = %d\n", freq ) ; 
  90.         //if( key == ESC_KEY ) 
  91.         //{ 
  92.         //  Buzzer_Stop() ; 
  93.         //  return ; 
  94.         //} 
  95.  
  96.     } 
  97.  
  98. */  
  99. }  
#include "pwm_uart_test.h"
extern void Buzzer_Freq_Set(int freq);
//extern void Buzzer_Freq_Set( void );
char uart_GetByte(void)
{
		while(!(rUTRSTAT0 & 0x1));   //Wait until THR is empty.
			return RdURXH0();
}


void uart_GetString(char *pt)
{
	while(*pt)
		uart_GetByte();
}


void uart_SendByte(int data)
{
	
		if(data=='\n')
		{
			while(!(rUTRSTAT0 & 0x2));
			WrUTXH0('\r');
		}
		while(!(rUTRSTAT0 & 0x2));   //Wait until THR is empty.
		WrUTXH0(data);

}               

//====================================================================
void uart_SendString(char *pt)
{
	while(*pt)
	       uart_SendByte(*pt++);
}


void uart_test(void)
{
	
	char str[20] = "\nhello world\n";
	int a = 97;
	//while(1)
	//	uart_SendByte(a);	
	uart_SendString(str);
	char s = uart_GetByte();
	//if(s == 'a')
	if(s == 97)
		rGPBDAT = 0x1c0;
	//uart_SendByte(a);
	//uart_SendByte(97);
	//uart_SendByte('a');
	uart_SendByte((int)s);
	uart_SendByte((int)'s');
}

void pwm_uart_test(void)
{
	int freq = 10;
	Buzzer_Freq_Set( freq ) ;
	//Buzzer_Freq_Set(  ) ;

	uart_SendString("start\n");
/*
	int i;
	for(i=0;i<1000;i++)
		uart_SendString("wait\n");
    while( 1 )
    {
		char key = uart_GetByte();
		uart_SendByte(key);
		if( key == 'a' || key == 'A' )
		{
			if( freq < 2000 )  //lci  20000
				freq += 10 ;
				uart_SendByte('a');
			Buzzer_Freq_Set( freq ) ;
		}

		if( key == 'b' || key == 'B' )
		{
			if( freq > 11 )
				freq -= 10 ;
				uart_SendByte('b');
			Buzzer_Freq_Set( freq ) ;
		}
		
		//uart_SendString( "\tFreq = %d\n", freq ) ;
		//if( key == ESC_KEY )
		//{
		//	Buzzer_Stop() ;
		//	return ;
		//}

	}

*/
}



在这个例子中,既有汇编调用c,也有c调用汇编.可供以后参考.目前,串口输入还有些问题,还得继续调一下.串口遇到一个想不明白的问题,单单串口是正常的,但在打开PWM定时器后,串口就出问题了,打印只能出前面几个字符,这是个神马情况,有人知道的请帮我下,thks!

从代码中有这样的设定:
定时器的输入时钟为@定时器输入时钟周期 = PCLK/(prescaler + 1)/(divider value)
@clk = 100M/(249+1)/8=25k


TCNTB0设为200,而TCMPB0为50,则TOUT0输出占空比为25%的方波,方波的周期为200/clk=8ms

如果有示波器,倒可以验证一下这个结果.如果有对朋友觉得这个方波估计的不对,欢迎指出,谢谢!

s3c2440产生pwm 利用s3c2440的4个定时器产生4路pwm,周期和脉宽可调 立即下载

相关推荐

嵌入式PWM定时器代码(ARM9)

基于s3c2440的pwm代码控制led灯的亮,灭。内有关于pwm寄存器的pdf文档。是学习嵌入式系统的入门程序,很适合初学者。

基于S3C2440的嵌入式Linux驱动——Framebuffer子系统解读

本文将介绍Framebuffer子系统 目标平台:TQ2440 CPU:s3c2440 LCD设备:3.5英寸,分辨率320X240 1. 概述 Framebuffer,中文名字是帧缓冲,这个帧也就是一副图像所需要的数据。因此,帧缓冲其实就是LCD设备的驱动程序。Linux中,framebuffer子系统框架如下: 核心层的代码以fbmem.c为主,核心层包括许多与具体硬

嵌入式Linux 6217

第八章 MobileNetv3网络详解

本文介绍了基于互补的搜索技术和新颖的架构设计的MobileNets的下一代。MobileNetV3通过硬件感知网络架构搜索(NAS)和NetAdapt算法相结合,针对移动电话CPU进行优化,随后通过新颖的架构改进技术进行了进一步提高。本文开始探索自动化搜索算法和网络设计如何相互协作,以利用互补的方法改进整体技术水平。通过此过程,我们创建了两个新的MobileNet模型:MobileNetV3-Large和MobileNetV3-Small,分别针对高资源和低资源使用情况。

ADICDFHL的博客 1万+

s3c2440时钟系统

1.s3c2440能够产生三种时钟,FCLK供给cpu,HCLK供给AHB总线设备,PCLK供给APB总线设备。它还有两个PLL,一个用于FCLK、HCLK、PCLK的时钟产生,另一个用于usb模块时钟。它的时钟源通过引脚OM3和OM2选择,我们外接的是12MH晶振,OM2和OM3都接地。这里需要注意的是上电复位后MPLL不工作,系统时钟为晶振或外部时钟源提供的时钟,必须设置MPLLCON才能启动

vv_sunshine的博客 702

用迅为RK3588开发板DIY无人机飞控:从电路设计到PID调参全记录

本文详细记录了使用迅为RK3588开发板DIY无人机飞控的全过程,从硬件选型、PCB设计到实时系统构建和PID调参。RK3588核心板凭借其强大的AI算力和丰富接口,成为高性能无人机控制解决方案的理想选择。文章还分享了视觉导航系统集成和实际飞行测试经验,为硬件爱好者提供实用参考。

weixin_29053577的博客 422

如何缩减layout电路面积?减少晶体管的数量——以全加器为例【VLSI】

How to reduce the number of transistors to reduce circuit area? -- Take the Binary Full Adder as an example 优化面积的方法 1. 减少晶体管的数量 2. 改变gate matrix的布局

Jie_MSD的博客 6429

Keil5 平台 S3C2440裸机程序开发-----PWM

本博文介绍mini2440开发板,在keil5平台上进行PWM开发的一些基本配置。

博客 666

AMBA VIP基础使用方式(AXI)

AXI环境配置 1)基础配置 作为master或者slave使用时,对应的is_active = 1 只作为i监测(monitor)使用时,对应slave_cfg的is_active = 0(对应端口连接也有所区别) class smu_axi_cfg extends svt_axi_system_configuration; `uvm_object_utils(smu_aix_cfg) function new(string name="smu_axi_cfg); super.new(n..

qq_37573794的博客 7984

s3c2440的时钟详解

     s3c2440 cpu的默认工作主频有两种12MHz和16.9344MHz,也就是我们的晶振的频率,但一般12MHz的晶振用的比较多,Fin就是指我们接的晶振频率。大家都知道s3c2440上电正常工作后频率是远远大于12MHz和16.9344MHz的,我们的s3c2440的cpu正常工作时的频率就是405MHz,因此这就需要一个电路来提升频率,在s3c2440的datasheet中找到了...

蛋蛋强的专栏 6379

48、基于头部电信号和触觉的人机交互技术研究

本文探讨了基于头部电信号控制决策和触觉感知的人机交互技术。通过EEG信号采集与ANN模型(TDNN/PRNN)分析,实现对用户意图的识别;同时利用触觉传感接口识别操作员有意接触,提升人机协作安全性。研究涵盖系统设计、数据处理流程、实验结果及技术拓展方向,并展望了两种技术在工业、医疗与智能家居等领域的融合应用前景。

i1j2k的博客 98

【论文复现】——基于LM优化的NDT点云配准算法

传统的正态分布变换配准算法处理初始位姿变换相差较大的两帧点云时,存在无法收敛或者陷入局部最小值的问题。为了提高算法的收敛性能,提出了一种基于LM方法改进的三维正态分布变换配准算法。

点云侠的博客 1163

GNU ARM汇编--(六)s3c2440的时钟控制

前面几篇利用GNU ARM汇编控制LED以及ARM的中断处理的设计,对ARM汇编以及体系结构有了一定的认识.后面的汇编学习会结合具体的芯片进行,一个为了更灵活熟练的使用汇编,二也是为了通过学习一款具体芯片来提炼出一些有价值的经验.此次选择的芯片是三星的s3c2440,arm920t的核,整个板子是TQ2440的板子,这个板子放了两年多了,零散的玩过一些,但是为了建立更有体系的知识结构,还...

dingxiu8587的博客 170

CDD数据库文件制作(二)——服务配置(0x27)

主要根据诊断调查表,针对0x27服务在CDD中的每一步配置给出详细介绍 1.会话切换配置 1.1.根据诊断调查表进行信息提取 1.2.子功能添加 1.2.1.Level1安全等级1创建 1.2.2.Level3安全等级3创建 1.2.3.安全等级名字查看与修改 1.3.会话切换信息提取(应用程序下) 1.4.会话转换配置(应用程序下) 1.5.会话切换信息提取(引导程序下) 1.6.会话转换配置(引导程序下) 2.安全等级配置信息提取 2.1.安全访问配置(level1) 2.2.安全访问配置(level2

LOVE135149的博客 2928

S3C2440驱动开发(一)

1.驱动开发概述 本文主要针对友善之臂mini2440开发板而编写的学习资料。虽然市面上介绍Linux系统驱动原理和内核源码的书很多,但是直接上手比较困难,特买了一个Arm9开发板,希望从裸机程序开始学习,逐步掌握Linux系统驱动开发方法。编写本文的目的为记录学习过程,用于后期回顾。文章主要分为两部分。第一部分,从友善之臂提供的裸机程序开始介绍各各外设驱动开发过程。第二部分,linux驱动开发流程及实践。 1.1 S3C2440A介绍 三星S3C2440是为手持式设备而开发的16/32位精简指令集微

mingjingtai2000的专栏 1150

Mac 下 OpenClaw 安装全记录:从零到一的保姆级图文教程

本文主要介绍了Mac 下 OpenClaw 安装全记录:从零到一的保姆级图文教程,希望能对学习使用OpenClaw 的同学们有所帮助。 文章目录 1. 背景 2. 安装教程 2.1 安装OpenClaw 2.2 配置模型 2.3 对话 3. 后续使用步骤 4. 关闭程序

weixin_43178406的博客 11万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

s3c2440 linux3.0下PWM使用之蜂鸣器驱动移植

这篇文档拖了好久了,都有点淡忘了。这段时间考试加实验太忙了,但还是先粗略的记录,总结下吧。 先贴上修改过的地方。文件:mach-smdk2440.c +#include //add by handy 5.20 +/* beeper add by Handy 2015.5.20 */ +static struct platform_device smdk2440_beeper_dev

2548

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

S3C2440驱动开发(四)

是

mingjingtai2000的专栏 323

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

S3C2440驱动开发(六)

裸机程序开发之蜂鸣器程序 先上代码,代码有点长,共409行。涉及到的寄存器比较多。本节只做代码解释,详细原理不再这里展开。 #include "def.h" #include "option.h" #include "2440addr.h" #include "2440lib.h" #include "2440slib.h" #include "mmu.h" //================================ #define LCD_WIDTH 240 #def...

mingjingtai2000的专栏 429

基于S3C2440的Linux-3.6.6移植 PWM蜂鸣器驱动

转载地址:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=23795897&id=4537163 Linux带有基于PWM蜂鸣器的通用驱动程序——Pwm-beeper.c(位于drivers/input/misc目录下),它是属于输入子系统的。因此要移植该驱动,只需要在自己的开发板程序文件中添加PWM蜂鸣器的平台设备及相关属性即

kunkliu的博客 732
上一篇: GNU ARM汇编--(八)s3c2440的watchdog
下一篇: GNU ARM汇编--(十)s3c2440的RTC
RubyBoss
博客等级 码龄17年 157粉丝 7原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值