icflashman

    1. ;****************************************************************************** ; * ; 文件名 : acim_vhz.s ; * ;****************************************************************************** ; 注: * ; ====== * ; A/D 用以对dsPICDEM-MC1 演示板上两个与AN7 和AN12 连接的电位计进行采样。 ; VR1 用来改变调制的V/Hz 比值。 VR2 用来改变调制频率。 通过用两个电位计进行试验, ; 可以找到一个最佳的V/Hz 比值来驱动电机。 ;******************************************************************************         .equ __30F6010, 1         .include "p30f6010.inc"         .global    __reset ;.............................................................................. ; 配置位: ;..............................................................................         config __FOSC, CSW_FSCM_OFF & XT_PLL4 ; 关闭时钟切换和         ; 故障保护时钟监视并         ; 使用XT 振荡器和4 倍频PLL 作为         ; 系统时钟         config __FWDT, WDT_OFF ; 关闭看门狗定时器         config __FBORPOR, PBOR_ON & BORV_27 & PWRT_16 & MCLR_EN         ; 设置欠压复位电压         ; 并将上电延迟定时器设置为16ms         config __FGS, CODE_PROT_OFF ; 对一般代码段         ; 将代码保护设置为关闭 ;.............................................................................. ; 近数据存储器(RAM 的低8KB)中的未初始化变量 ;..............................................................................         .section .nbss, "b"                                     ; 在每个PWM 周期将此变量加到16 位的                                     ; 正弦波数值表指针。对于16 KHz 的PWM 调制,数值246 将提供                                     ;60 Hz 的调制频率         Frequency:.space 2                                     ; 此变量用来设置调制幅值并换算                                     ; 从正弦波数值表获取的值。有效值的范围为0 到32767         Amplitude:.space 2                                     ; 此变量是正弦波数值表的指针。在每次PWM 中断时,                                     ; 它递增一次,递增数值是Frequency 变量的值。         Phase: .space 2 ;.............................................................................. ; 存储在程序空间中的常数 ;..............................................................................         .section .sine_table, "x"         .align    256         ; 这是一个含有64 个值的正弦波表,覆盖了正弦函数的360 度。         ; 使用Microsoft Excel 计算这些值并将它们粘贴到此程序中。         SineTable:         .hword 0,3212,6393,9512,12539,15446,18204,20787,23170,25329         .hword 27245,28898,30273,31356,32137,32609,32767,32609,32137,31356,30273,28898         .hword 27245,25329,23170,20787,18204,15446,12539,9512,6393,3212,0,-3212,-6393         .hword -9512,-12539,-15446,-18204,-20787,-23170,-25329,-27245,-28898,-30273         .hword -31356,-32137,-32609,-32767,-32609,-32137,-31356,-30273,-28898,-27245         .hword -25329,-23170,-20787,-18204,-15446,-12539,-9512,-6393,-3212         ;数据计算,64个值 ;.............................................................................. ; 此应用程序中的常数 ;..............................................................................         ; 此常量用来将正弦查找值换算到PWM 占空比的有效范围内。占空比的范围取决于写入PTPER 的值。         ; 对于此应用程序,我们将设置PTPER = 230,使占空比介于0 和460 之间。正弦表数据是有符号的,         ; 我们用230 乘以表中数据,然后将乘积加上固定的偏移值从而将查找数据换算为正值         .equ PWM_Scaling, 230         ; 正弦波表的指针是16 位的。把0x5555 加给         ; 指针将提供120 度的偏移,而加上0xAAAA 将提供240         ; 度的偏移。这些偏移用来获取PWM 输出的相位2 和相位3 的查找值。         .equ Offset_120, 0x5555 ;.............................................................................. ; 程序存储器中的代码部分 ;..............................................................................         .text ;代码部分的开始         __reset:         MOV #__SP_init, W15 ; 初始化堆栈指针         MOV #__SPLIM_init, W0 ; 初始化堆栈指针限制寄存器         MOV W0, SPLIM         NOP ; 在初始化SPLIM 之后,加一条NOP         CALL _wreg_init ; 调用 _wreg_init 子程序         ; 可以选用RCALL 代替CALL         call Setup ; 调用程序以设置I/O 和PWM ;------------------------------------------------------------------------------ ; 初始化变量 ;------------------------------------------------------------------------------         clr Frequency                 clr Amplitude ;------------------------------------------------------------------------------ ; 主循环代码 ; 在主循环中查询PWM 中断标志 ;------------------------------------------------------------------------------         Loop: btss IFS2,#PWMIF ; 查询PWM 中断标志         bra CheckADC ; 如果置1,则继续         call Modulation ; 调用正弦波调制程序         bclr IFS2, #PWMIF ; 清零PWM 中断标志         CheckADC:         btss IFS0,#ADIF         bra Loop         call ReadADC         bra Loop ;------------------------------------------------------------------------------ ; ADC 处理子程序 ;------------------------------------------------------------------------------         ReadADC:         push.d W0         push.d W4         mov ADCBUF0,W0 ; 将ADC 结果读入W0         mov ADCBUF1,W1 ; 和W1。         asr W0,#2,W4 ; 右移2 位以得到         mov W4,Frequency ; 调制频率。         sl W1,#5,W4 ; 将AN7 和AN12 的值左移以得到         sl W0,#5,W5 ; 1.15 格式的小数数据。         mpy W4*W5,A ; 将频率与V/Hz 的商相乘得到         sac A,W0 ; 调制幅值。将结果存储在W0 中。         mov #28000,W1 ; 限制调制幅值以避免         cp W1,W0 ; 在PWM 调制中由死区引起的         bra GE,NoLimit ; 失真。         mov W1,W0         NoLimit:         mov W0,Amplitude         pop.d W4         pop.d W0         return ;------------------------------------------------------------------------------ ; PWM 正弦波调制子程序 ;------------------------------------------------------------------------------         Modulation:         push.d W0 ; 保存工作寄存器         push.d W2         push.d W4         push.d W6         push.d W8         push.d W10         ; 下面的三条指令初始化TBLPAG 和指针寄存器         ; 从而可使用读表操作来访问程序存储器中的正弦波数据。         mov #tblpage(SineTable),W0                     mov W0,TBLPAG                        ;写入表的页地址                 mov #tbloffset(SineTable),W0         ; 下面的指令块装载正弦波调制程序中使用的各种常数和变量。         mov Phase,W1                         ; 装载正弦波表指针         mov #Offset_120,W4                     ; 这是120 度偏移的值         mov Amplitude,W6                     ; 装载幅值换算系数         mov #PWM_Scaling,W7                 ; 装载PWM 换算值         mov Frequency,W8                     ; 装载将在每次中断时与表指针相加的Frequency 常数。         ; 这是指针调节代码。将Frequency 值加给正弦表指针以使指针在正弦表中前移。         ; 然后,为此指针加上相应的偏移值以得到相位2 和相位3 的指针。         ; 注意:如果需要不同的相位偏移,可以在这里使用其他常数值。         ; 加上0x4000 将得到90 度偏移,加上0x8000 将         ; 提供180 度偏移。 在此将0x5555 装入W4 以提供120 度偏移。         add W8,W1,W1 ; 将Frequency 值加给正弦指针         add W1,W4,W2 ; 加上120 度偏移值以得到相位2 的指针         add W2,W4,W3 ; 再加上120 度偏移以得到相位3 的指针         ; 该正弦表有64 个值,所以将指针右移         ; 以得到一个6 位的指针值。         lsr W1,#10,W9 ; 将相位1 的指针右移以得到高6 位         sl W9,#1,W9 ; 左移一位转换为字节地址         lsr W2,#10,W10 ; 将相位2 的指针右移以得到高6 位         sl W10,#1,W10 ; 左移一位转换为字节地址         lsr W3,#10,W11 ; 将相位3 的指针右移以得到高6 位         sl W11,#1,W11 ; 左移一位转换为字节地址         ; 现在,将每个相位的指针与基表指针相加以获得查找值的绝对表地址。         ; 然后将查找值换算为正确的幅值和在有效的占空比范围之内。         ; 下面的指令块为相位1 计算占空比。为相位2 和相位3 计算占空比的代码与此相同。         add W0,W9,W9 ; 形成相位1 的表地址         tblrdl [W9],W5 ; 读相位1 的查找值         mpy W5*W6,A ; 乘以幅值换算系数         sac A,W5 ; 存储经过换算的结果         mpy W5*W7,A ; 乘以PWM 换算系数         sac A,W8 ; 存储经过换算的结果         add W7,W8,W8 ; 加上PWM 换算系数以产生50% 的偏移         mov W8,PDC1 ; 写PWM 占空比         ; 下面的代码块为相位2 计算占空比。         add W0,W10,W10 ; 形成相位2 的表地址         tblrdl [W10],W5 ; 读相位2 的查找值         mpy W5*W6,A ; 乘以幅值换算系数         sac A,W5 ; 存储经过换算的结果         mpy W5*W7,A ; 乘以PWM 换算系数         sac A,W8 ; 存储经过换算的结果         add W7,W8,W8 ; 加上PWM 换算系数以产生50% 的偏移         mov W8,PDC2 ; 写PWM 占空比         ; 下面的代码块为相位3 计算占空比。         add W0,W11,W11 ; 形成相位3 的表地址         tblrdl [W11],W5 ; 读相位3 的查找值         mpy W5*W6,A ; 乘以幅值换算系数         sac A,W5 ; 存储经过换算的结果         mpy W5*W7,A ; 乘以PWM 换算系数         sac A,W8 ; 存储经过换算的结果         add W7,W8,W8 ; 加上PWM 换算系数以产生50% 的偏移         mov W8,PDC3 ; 写PWM 占空比         ; 现在,保存经过调节的正弦波表指针从而能         ; 在此代码的下一次迭代中使用它。         mov W1,Phase         pop.d W10 ; 恢复工作寄存器         pop.d W8         pop.d W6         pop.d W4         pop.d W2         pop.d W0         return ; 从子程序返回 ;------------------------------------------------------------------------------ ; PWM 和ADC 的设置代码 ;-------------------------------------------------------------------------------------         Setup:         ; 在使能PWM 之前需要做的第一件事是配置I/O 并复位电源模块。         ; 该控制板有一个缓冲PWM 控制线的驱动器IC。         ; RD11 端口上的有效低电平使能该缓冲器。         ; 此电源模块有一条与端口RE9 相连的高电平有效复位线路。         clr PORTD         clr PORTE         mov #0xF7FF,W0 ; 设置RD11 输出驱动PWM 缓冲器         mov W0,TRISD ; 使能。         mov #0xFDFF,W0;         mov W0,TRISE ; 设置RE9 输出复位电源模块         ; 现在,通过驱动复位线并保持几个微秒来确保电源模块复位。         bset PORTE,#9         repeat #39         nop         bclr PORTE,#9         ; 设置ADC         mov #0x0404,W0 ; 扫描输入         mov W0,ADCON2 ; 每次中断进行2 次采样/ 转换         mov #0x0003,W0;         mov W0,ADCON3 ; Tad 是2 个Tcy         clr ADCHS ;         clr ADPCFG ; 将所有A/D 引脚设置为模拟模式         clr ADCSSL ;         bset ADCSSL,#7 ; 使能对AN7 的扫描         bset ADCSSL,#12 ; 使能对AN12 的扫描         mov #0x8066,W0 ; 使能A/D、PWM 触发和自动采样         mov W0,ADCON1 ;         bclr IFS0,#ADIF ; 清零A/D 中断标志位         ; 现在设置PWM 寄存器         mov #0x0077,W0 ; 互补模式,使能#1、#2 和#3         mov W0,PWMCON1 ; 三对PWM 输出         mov #0x000F,W0 ; 器件运行速度为7.38 MIPS 时,将产生2μs 的死区         mov W0,DTCON1         mov #PWM_Scaling, W0 ; 器件运行速度为7.38 MIPS 时,为16KHz PWM 设置周期         mov W0,PTPER         mov #0x0001,W0 ;         mov W0,SEVTCMP ; 将ADC 设置为以特殊事件触发启动         mov #0x0F00,W0 ; 将特殊事件后分频比设置为1:16         mov W0,PWMCON2 ;         mov #0x8002,W0 ; 使能PWM 时基,中心对齐模式         mov W0,PTCON         return ; 从Setup 子程序返回 ;.............................................................................. ; 子程序:将W 寄存器初始化为0x0000 ;..............................................................................         _wreg_init:         CLR W0         MOV W0, W14         REPEAT #12         MOV W0, [++W14]         CLR W14         RETURN ;-------- 所有代码部分结束---------------------------------------------         .end ; 此文件中程序代码的结尾

最近访客

< 1/1 >

统计信息

已有31人来访过

  • 芯积分:--
  • 好友:--
  • 主题:--
  • 回复:1

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言