📄 setup.c
字号:
/**********************************************************************
* 程序说明
*
* 该文件包含所有的dsPIC外围设备设置子程序,此外还有WriteConfig()函数,
* 该函数可以在运行时间配置芯片的位,尤其是WriteConfig()还可以反转PWM
* 输出信号的极性;在PWM运行周期的结束点,PWM用于触发A/D转换。这样可以
* 保证AD能够及时被触发,不管PWM的占空比如何,要完成这项功能,用户必须
* 把占空比值写入PDC寄存器。
* ADC在此点触发
* |
* PWM1 _____ _______________
* |________________| |_______
*
* PWM2 _____ _______________________
* |________| |_______
*
* PWM3 _____ _________
* |______________________| |_______
*
*
**********************************************************************/
#include "general.h"
#include "hardware.h"
#include "defs.h"
#include "extern_globals.h"
void setup_ports(void);
void setup_motor_pwms(void);
void setup_adc(void);
void setup_qei(void);
void setup_timers(void);
unsigned int ReadConfig(int);
void WriteConfig(int,int);
#ifdef DEVELOPMODE
void setup_uart(void);
#endif
//设置端口子程序
void setup_ports(void)
{
//清所有的端口
PORTB=0;
PORTC=0;
PORTD=0;
PORTE=0;
//确保禁止点火
DISABLE_FIRING;
//设定端口方向
TRISB = 0xFFFF; // RB15:输出比较错误 -> 输入
// RB14-0:模拟端口 -> 输入
TRISC = 0x6000; // RC14: S2起始/停止开关 -> 输入
// RC13: S3 后退/前进开关 -> 输入
// 其余的C端口设定为输出
TRISD = 0x0003; // RD0-1:调试EMUC2/EMUD2 -> 输入
// 其余的D端口设定为输出
TRISE = 0x0100; // RE8: PWM出错按钮 -> 输入
// RE5-0:PWM信号 -> 输出
return;
}
//设置马达PWM子程序
void setup_motor_pwms(void)
{
unsigned int config_value,temp;
//时基控制
PTCON = 0x8000; //时基开,运行与空闲模式,无预置或后置,自由运行
//周期寄存器 :自由运行时PWM周期为(PTER+1) * Tcy * Prescaler
PTPER = FULL_DUTY/2; //7.3728MHz指令频率,无预置
//当FULL_DUTY= 922时,PWM为16kHz
//特定事件触发控制
SEVTCMP = FULL_DUTY/2; // 开关关之前立即触发
//PWM控制寄存器#1
PWMCON1 = 0x0700; // 第4项点火信号不用,其余的独立
//PWM控制寄存器#2
PWMCON2 = 0x0000; //无特殊事件预置,快速超越,使能更新
//停滞时间控制寄存器
DTCON1 = 0x0000; // 禁止停滞时间
//错误A输入控制寄存器
FLTACON = 0xFF0F; //锁存FLTA所有引脚激活
//改写控制寄存器
OVDCON = 0x3FFF; // 所有输出产生PWM,所有超越状态激活
// PDC1-4 - PWM#1-4 占空比寄存器
PDC1=FULL_DUTY; //在此种情况下占空比满值
PDC2=FULL_DUTY;
PDC3=FULL_DUTY;
config_value=ReadConfig(4);
temp=config_value;
temp=(temp & 0x0700)>>8;
//如果PWM极性和复位定义位正确设置,temp=4
if (temp != 4)
{
config_value &= 0xF0FF;
config_value |= 0x0400;
//写新值到F80004
WriteConfig(4,config_value);
}
IFS2bits.PWMIF = 0;
IFS2bits.FLTAIF =0;
return;
}
//设置ADC子程序
void setup_adc(void)
{
// ADC控制寄存器#1
ADCON1 = 0x006F; //采用PWM触发,连续同时采样
// ADC控制寄存器#2
ADCON2 = 0x0200; //参考电压采用Avdd/Avss, 转换CH0、CH1、CH2 和CH3共4个通道,不扫描
//完成每个采样/ 转换过程后产生中断,总是使用MUX A 输入多路开关设置
// ADC控制寄存器#3
ADCON3 = 0x0003; // 不采用自动采样,A/D时钟由系统时钟产生(2Tcy),
// 转换时间大约3us,7.3728Mhz X4 PLL时给出271ns Tad
// A/D输入选择寄存器
ADCHS = VPH_RED; //MUXB不用, MUXA-ve=Vss,对CH1-3通道+ve=AN0-2
//对CH0 -ve=Vss,+ve=AN12
// ADC端口配置寄存器
ADPCFG = 0x8000; //AN15引脚:模拟输入引脚处于数字模式,使能端口读取输入, A/D 输入多路开关输入连接到AVSS
//所有其他端口:模拟输入引脚处于模拟模式,禁止端口读取输入, A/D 采样引脚电压
// A/D 输入扫描选择寄存器
ADCSSL = 0x7020; //选择对AN5, AN12-14 输入进行扫描
// 清A/D中断
IFS0bits.ADIF = 0;
// 打开ADC模块
ADCON1bits.ADON=1;
return;
}
//设置QEI子程序
void setup_qei(void)
{
//QEI控制寄存器
QEICON = 0x0910; //在空闲模式下,模块继续工作,位置计数器方向为正(+), 启动16 位定时器,
//相位A 和相位B 输入已交换,位置计数器方向状态输出为正常的I/O 引脚,定时器输入时钟预分频比1:64(7372800/64 = 115.2kHz )
//数字滤波器控制寄存器
DFLTCON = 0x0000;//数字滤波器输出为正常的引脚,数字滤波器时钟分频1:1,数字滤波器输出禁止
MAXCNT = 0xffff; //最大计数寄存器设为满值
IFS2bits.QEIIF=0; //清QEI中断
return;
}
//设置定时器子程序
void setup_timers(void)
{
// Timer 1为守护时间,用于捕捉丢失的过零事件,以防止过流。
// Timer 2用于记时换向事件的时间间隔
// Timer 3用于准时关闭闸刀开关,
//时基寄存器#1
T1CON= 0x8020; //定时器开, 在空闲模式定时器继续工作,定时器输入时钟预分频为1:64
//时钟预分频与T2 和 QEI匹配
PR1=0xFFFF; //设置周期匹配寄存器为满值
IFS0bits.T1IF=0; //清T1中断标志
//时基寄存器#2
T2CON=0x8020; //定时器开, 在空闲模式定时器继续工作,定时器输入时钟预分频为1:64
//时钟预分频与QEI匹配,用作“输入捕捉”
PR2=0xFFFF; //设置周期匹配寄存器为满值
IFS0bits.T2IF=0; //清T2中断标志
//时基寄存器#3
T3CON=0x8020; //定时器开, 在空闲模式定时器继续工作,定时器输入时钟预分频为1:64
PR3=0xFFFF;
IFS0bits.T3IF=0; //清T3中断标志
return;
}
//在指定地址读值子程序
unsigned int ReadConfig(int address)
{
//表页指向配置页
asm(" mov.w #0x00F8,w2");
asm(" mov.w w2,TBLPAG");
//读值
asm(" tblrdl [w0],w0");
//返回所读的值
return WREG0;
}
//在指定地址写值子程序
void WriteConfig(int address, int value)
{
//表页指向配置页
asm(" mov.w #0x00F8,w2");
asm(" mov.w w2,TBLPAG");
// 设定NVMCON值,开始写
asm(" mov.w #0x4008,w2");
asm(" mov.w w2,NVMCON");
// 写值
asm(" tblwtl W1,[W0]");
asm(" bset NVMCON,#14");
asm(" mov #0x55,W2 ");
asm(" mov W2,NVMKEY ");
asm(" mov #0xaa,W2 ");
asm(" mov W2,NVMKEY ");
asm(" bset NVMCON,#15");
while(NVMCONbits.WR);
}
#ifdef DEVELOPMODE
//设定UART子程序
void setup_uart(void)
{
U1MODE = 0x8000;
U1STA = 0x0000;
U1BRG = ((CLOCK_FREQ/16)/BAUD) - 1; //设定波特率
IEC0bits.U1RXIE = 1;
RXPtr = &InData[0]; //指向接收字符串的首字符
control_flags2.CheckRX = 0;
control_flags2.SendTX = 0;
U1STAbits.UTXEN = 1; //初始化数据传输
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -