⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 setup.c

📁 dspic开发控制程序,有助开发pic单片机程序
💻 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 + -