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

📄 main.c

📁 基于ARM的电压控制,且有两级调制,可以实现精确的电压输出
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************Copyright (c)**************************************************
**                               Guangzou ZLG-MCU Development Co.,LTD.
**                                      graduate school
**                                 http://www.zlgmcu.com
**
**--------------File Info-------------------------------------------------------------------------------
** File name:			main.c
** Last modified Date:  2004-09-16
** Last Version:		1.0
** Descriptions:		The main() function example template
**
**------------------------------------------------------------------------------------------------------
** Created by:			Chenmingji
** Created date:		2004-09-16
** Version:				1.0
** Descriptions:		The original version
**
**------------------------------------------------------------------------------------------------------
** Modified by:			Chenxibing
** Modified date:		2005-01-14
** Version:
** Descriptions:		SPI实验,74HC595驱动7段数码管。
**
********************************************************************************************************/
//程序名:keyboard_display_I2C_PWM_4_AD_4_CAP_4


//----------------------程序头-----------------------------------
#include  "config.h" 

#define   HC595_CS       (1 << 29)      // P0.29口为74HC595的片选
#define   KEY            (1 << 5)      // P0.5口(MISO)为按键输入脚

#define 	Uo_def		CS[0]		//设定的电压 (第1级的)
#define 	Uo_test		CS[1]		//实测电压
#define 	Vref		CS[2]       //基准电压?????????????
#define 	Duty		CS[3]       //占空比的分子
//#define     Uin			CS[4]

#define 	Uo2_def		CS[4]		//设定的电压(第2级的)
#define 	Uo2_test	CS[5]		//实测电压
#define 	Duty2		CS[7]       //占空比的分子
#define 	AD2SHOW		CS[6]		//AD2出的值

uint32 Uin=10000;                   //输入电压, mV

uint8  T0Flag = 0;                  //定时中断标志           
uint16 CS[8]={0,0,0,0,0,0,0,0};
uint8 data_buf[12];
uint8  DATA0[8],DATA1[8];			
uint8  digitable[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uint8  selectable[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uint8  x=0,y=0,k=0;  //指针型变量,k对DATA0&DATA1&selectable;x&y对digitable;
uint8  w=0; 			 //计数寄存器
uint8 SF=0;    			 //闪烁标志位
uint8 TK=0x09;			 //按键按下位寄存器
uint8 M=0,R=0;			 //按键选项寄存器

uint8 Display=0;			//显示内容积存器
uint32 CAP1_1=0,CAP1_2=0,CAP1_3=0,CAP1_4=0;  
uint32 CAP2_1=0,CAP2_2=0,CAP2_3=0,CAP2_4=0;	   //定义捕获值寄存器组
uint32 PLS1=0,PLS2=0,PLS3=0,PLS4=0;		//捕获脉冲总次数寄存器
uint8 H1=0,H2=0,H3=0,H4=0;               //首次捕获标志位
uint16 N1=0,NP1=0,N2=0,NP2=0,N3=0,NP3=0,N4=0,NP4=0;	//捕获次数寄存器及其暂存器
uint16 F1=0,F2=0,F3=0,F4=0;	            //未知信号频率寄存器
uint16 ADC_Data1[8]={0,0,0,0,0,0,0,0};	//AD转换结果暂存区
uint16 ADC_Data2[8]={0,0,0,0,0,0,0,0};
uint16 ADC_Data3[8]={0,0,0,0,0,0,0,0};
uint16 ADC_Data4[8]={0,0,0,0,0,0,0,0};
uint8 SENT_F;							//送数显示执行标志位



uint16 ADC_Data;		//第1级 AD值的寄存器
uint16 ADC2_Data;		//第2级 AD值的寄存器

uint16 dDuty;           //第1级 占空比增量
uint16 S_Flag;          //????????
uint16 rcv_data;        //????????
uint16 dUo;             //第1级测量电压增量             

uint16 Adj_Flag;	//调整时间标志
uint32 sum_data;	//AD 累加和
uint32 adc_count;	//AD 次数

uint16 display = 2;		//屏幕寄存器:1-为第1屏  2-为第2屏
uint16 dDuty2;          //第2级 占空比增量
uint16 S_Flag2;         //????????
uint16 dUo2;            //第2级测量电压增量 

uint32 sum2_data;	//AD2 累加和
uint32 adc2_count;	//AD2 次数
//………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………

/*********************************************************************************************************
** 函数名称 :delays()
** 函数功能 :长软件延时
** 入口参数 :dly	延时参数,值越大,延时越久
** 出口参数 :无
**********************************************************************************************************/
void delays(void)
{ uint8 i,j;
   for(i=100;i>0;i--)
     for(j=50;j>0;j--);
}//………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………




/***************TIMER0 初始化*************************************************************
** 函数名称:Timer0_InitExt()
** 功能描述:TIMER0 初始化
** 入口参数:无
** 出口参数:无
*******************************************************************************************/
void Timer0_InitExt(void)
{
	T0TC   = 0;			/* 定时器设置为0							*/
	T0PR   = 0;			/* 时钟不分频								*/
	T0MCR  = 0x03;		/* 设置T0MR0匹配后复位T0TC,并产生中断标志	*/
	T0MR0  = Fpclk/400; /* 2.5毫秒定时								*/
    T0TCR  = 0x01;		// 启动定时器	
}
/*************TIMER0 中断服务程序****************************************************************
** 函数名称:IRQ_Timer0()
** 功能描述:TIMER0 中断服务程序
** 入口参数:无
** 出口参数:无
*******************************************************************************************/
void __irq IRQ_Timer0(void)
{
	Adj_Flag++;								//A/D采样,调整时间到标志,2.5*8=20ms调整一次
	T0Flag = 1;								// T0中断标志置位
	T0IR = 0x01;							// 清除中断标志
	VICVectAddr = 0;						// 向量中断处理结束  清除中断标志
}
/************设置定时器0中断IRQ************************************************************
** 函数名称:IRQ_Init()
** 功能描述:设置定时器0&1及I2C中断IRQ
** 入口参数:无
** 出口参数:无
*******************************************************************************************/
void IRQ_Init(void)
{	
	VICIntSelect = 0x00000000;				// 设置所有的通道为IRQ中断
	VICVectCntl0 = 0x20 |0x04;				// Timer0分配到IRQ slot0,即最高优先级
	VICVectAddr0 = (uint32)IRQ_Timer0;	// 设置中断服务程序地址					
	VICIntEnable = 1 << 0x04;			// 使能定时器0中断						
}
//…………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………







//二进制数转BCD码子程序0
void CONVBIT0(uint16 num,uint8 hor)
{	
DATA0[hor] = num%10/1;
DATA0[hor+1] = num%100/10;
DATA0[hor+2] = num%1000/100;
DATA0[hor+3] = num/1000; 
return;	
}
//二进制数转BCD码子程序1
void CONVBIT1(uint16 num,uint8 hor)
{
DATA1[hor] = num%10/1;
DATA1[hor+1] = num%100/10;
DATA1[hor+2] = num%1000/100;
DATA1[hor+3] = num/1000;
return;
}

/********************************************************************************************************
** 函数名称:MSPI_Init()
** 函数功能:初始化SPI接口,设置为主机。
** 入口参数:无
** 出口参数:无
*********************************************************************************************************/
void  MSPI_Init(void)
{  
    S0PCCR = 0x52;		            // 设置SPI时钟分频
 	S0PCR  = (0 << 3) |				// CPHA = 0, 数据在SCK 的第一个时钟沿采样
 			(1 << 4) |				// CPOL = 1, SCK 为低有效
 			(1 << 5) |				// MSTR = 1, SPI 处于主模式
 			(0 << 6) |				// LSBF = 0, SPI 数据传输MSB (位7)在先
 			(0 << 7);				// SPIE = 0, SPI 中断被禁止
}

/********************************************************************************************************
** 函数名称:MSPI_SendData()
** 函数功能:向SPI总线发送数据。
** 入口参数:data   待发送的数据
** 出口参数:返回值为读取的数据
********************************************************************************************************/
uint8  MSPI_SendData(uint8 data)
{  
    SPI_SPDR = data;
    while( 0 == (SPI_SPSR & 0x80));		// 等待SPIF置位,即等待数据发送完毕
    return(SPI_SPDR);
}



/********************************************************************************************************
** 函数名称:PWM_Init()
** 函数功能:PWM初始化
** 入口参数:无
** 出口参数:无
*********************************************************************************************************/
void PWM_Init(void)
{
	PWMPR    = 0x00;		    // 不分频,计数频率为Fpclk
    PWMMCR   = 0x02;			// 设置PWMMR0匹配时复位PWMTC
    
    PWMPCR   = 0x0A00;			// 允许PWM1.3输出,单边PWM
    PWMMR0   = Fpclk/1000;   // 设置PWM频率 10KHz
    
 	PWMMR1   = (Duty2 * PWMMR0) / 10000 ;		// 占空比2	
 	PWMMR3   = (Duty * PWMMR0) / 10000 ;		// 占空比	
    
    PWMLER   = 0x0B;			// PWM0和PWM3, 1 匹配锁存
    PWMTCR   = 0X02;			//复位
    PWMTCR   = 0X09;			//启动PWM输出

} 




/********************************************************************************************************/
	/* 进行ADC模块设置 */
//AD初始化
//*******************************************************************************************************
void AD_Init(void)
{
	AD0CR = (1 << 3)				|			// SEL=8,选择通道3
	((Fpclk / 1000000 - 1) << 8)	|			// CLKDIV=Fpclk/1000000-1,转换时钟为1MHz
			(0 << 16)				|			// BURST=0,软件控制转换操作
			(0 << 17)				|			// CLKS=000, 使用11clock转换
			(1 << 21)				|  			// PDN=1,正常工作模式
			(0 << 22)				|  			// TEST1:0=00,正常工作模式
			(1 << 24)				|			// START=1,直接启动ADC转换
			(0 << 27);						 	// 直接启动ADC转换时,此位无效
	delays();
	ADC_Data = AD0DR;		// 读取ADC结果,并清除DONE标志位,为下次准备
}
/********************************************************************************************************
** 函数名称:ADC()
** 函数功能:AD转换程序
** 入口参数:无
** 出口参数:无
*********************************************************************************************************/
//启动 第1级 AD,并读取AD后的结果
//*********************************************************************

void StartADC(void)
{
	AD0CR = (AD0CR & 0xffffff00) |
			(1 << 3)			 |		// 通道3 AD0.3
			(1 << 24);					// 进行第一次转换
			
	while ((AD0DR & 0x80000000) == 0);	// 等待转换结束
	AD0CR = AD0CR | (1 << 24);					// 再次启动转换
	while ((AD0DR & 0x80000000) == 0);	// 等待转换结束
	ADC_Data = AD0DR;					// 读取ADC结果
	ADC_Data = (ADC_Data >> 6) & 0x3ff; //真正的结果
}
//*********************************************************************
//启动 第2级 AD2,并读取AD后的结果
//对第2级的输出进行采样
//*********************************************************************

void StartADC2(void)
{
	AD0CR = (AD0CR & 0xffffff00) |
			(1 << 5)			 |		// 通道5 AD0.5
			(1 << 24);					// 进行第一次转换
			
	while ((AD0DR & 0x80000000) == 0);	// 等待转换结束
	AD0CR = AD0CR | (1 << 24);					// 再次启动转换
	while ((AD0DR & 0x80000000) == 0);	// 等待转换结束
	ADC2_Data = AD0DR;					// 读取ADC结果
	ADC2_Data = (ADC2_Data >> 6) & 0x3ff; //真正的结果
}    
/*================================================================
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++==
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
 	
int main (void)
{// add user source code 

//Uin = 10000;		//mv
//CS[1] = 5000;
Uo_def = 8000;						//第1级 的相关设定
Uo_test = 0;
Vref = 2440;
Duty = (Uo_def * 10000 )/ Uin ;		//万份之几 的占空比( 扩大了10000倍的)
//Duty = (uo_def / uin) * 10000;	//不能这样写,因为前面除了以后是小于1的,系统取整后为0,要先做乘法!

Uo2_def = 3000;						//第2级 的相关设定
Uo2_test = 0;
Duty2 = (Uo2_def * 10000 * 10) / ((3300 * 10) * 2) ;		//万份之几 的占空比( 扩大了10000倍的)

	
	PINSEL0 = (PINSEL0 & (~0X03)) | (1 << 1) ;						//PWM1输出  P0.0  --控制第2级的
	PINSEL0 = (PINSEL0 & (~(0X03 << 2))) | (1 << 3);				//PWM3输出  P0.1  --控制第1级的

	PINSEL1 = (PINSEL1 & (~(0X03 << 20 ))) | (0X01 << 20) ;  	//AIN5 输入	P0.26  第2级
	PINSEL1 = (PINSEL1 & (~(0X03 << 28 ))) | (0X01 << 28) ;  	//AIN3 输入	P0.30  第1级

	IO0DIR = HC595_CS;							

	IRQEnable();						//IRQ中断使能
	IRQ_Init();
	Timer0_InitExt();
	MSPI_Init();
	PWM_Init();
	AD_Init();
	
while (1)
{	
	if (T0Flag==1)			//定时到  if1
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^		
   	 {  
    	if(T0Flag)									//中断定时到2.5ms
    	{
    		while(w==80)							//显示数据刷新时间到,执行数据变换. 2.5*80=200ms
			{
				if(M==0)							//如果M=0表示运行态,显示运行参数。
				{//
					if (display == 2)		//显示第2屏幕
					{
						CONVBIT0(CS[4],0);	//第2级 设定电压			//第一行低4位数码	
						CONVBIT0(CS[5],4);	//第2级 实测电压			//第一行高4位数码
						CONVBIT1(CS[6],0);	//第2级 占空比 				//第二行低4位数码
						CONVBIT1(CS[7],4);	//第2级 A/D出来的10bit	 	//第二行高4位数码
					}
					else					//显示第1屏幕
					{					
						CONVBIT0(CS[0],0);	//第1级 设定电压			//第一行低4位数码	
						CONVBIT0(CS[1],4);	//第1级 实测电压			//第一行高4位数码
						CONVBIT1(CS[2],0);	//第1级 基准电压			//第二行低4位数码
						CONVBIT1(CS[3],4);	//第1级 占空比				//第二行高4位数码
					}
				}//
				w=0;								//清除显示刷新计数器
				if(SF)								//闪烁标志取反
				SF=0;
				else
				SF=1;				
			}
//--------------------------------------------------------------------------------------------------------			
			if(M==0)								//显示扫描送运行参数
			{
				x=DATA0[k];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -