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

📄 main.c

📁 在凌阳61板上实验成功的电压表程序
💻 C
字号:


#include "math.h"
#include "a2000.h"
#include "hardware.h"
#include "LedTiSnd.h"

#define  true  1
#define  false 0

#define	 SND_DI_BASE 0				//嘀
#define  SND_REP_BASE  1			//现在时刻
#define	 SND_HOUR	24				//点
#define  SND_POINT	24				//点
#define  SND_MIN	25				//分
#define  SND_SEC	26				//秒
#define	 SND_NUM_BASE  6			//零(<=16)

#define		SPK_TIME 	10    		//报时间隔一次(s)
#define		SPK_VOLUME	1			//音量

#define		MIN_SWITCH_TIME	512*2	//持续按下 2S 那么开启 V ADC 功能,关闭计时功能
#define		MIN_REALSPK_TIME	128		//0.25S
#define		MIN_VOLAGE_STBTIME	512     //1S


unsigned int g_spk_arr[32] = {0};				//播放列表
unsigned int g_spk_arr_idx = 0;					//播放列表的长度
unsigned int g_spk_time_count = 0;				//报时计数
unsigned char g_start_spk = false;

unsigned char g_led_index = 0;					//当前显示的led序号

//从右至左(最右边为秒)
char g_led_sec_lo = 0;
char g_led_sec_hi = 0;
char g_led_min_lo = 0;
char g_led_min_hi = 0;

char g_old_sec_lo = 0;
char g_old_sec_hi = 0;
char g_old_min_lo = 0;
char g_old_min_hi = 0;

unsigned int g_base_2HZ_count = 0;

unsigned char g_vdc_enable = false;					//当前是否处于电压测量状态
unsigned int g_vdc_start_timecount = false;
unsigned char g_vdc_set_parameter = false;

unsigned int g_volage_stbtime = 0;					//稳定时间
unsigned char g_already_spk_volage = false;			//是否已经自动报告了电压值

int g_switch_timecount = 0;
unsigned char g_start_realtime_spk = false;				//如果为true将终止当前定点报时,开始按键报时


int main()
{	
	int i = 0;
	unsigned long int uiData = 0;
	unsigned int a,b,c,d;
	
	__asm("int off");
	
	//特设IOA4 带下拉电阻的输入,其他为带数据缓存器的高电平输出(无数据反相功能)
	*P_IOA_Attrib = (0xffff&(~0x0010));
	//*P_IOA_Dir = (0xffff&(~0x0010));
	*P_IOA_Dir = (0xffff&(~0x0010))&(~0x0020);		//IOA5悬浮输入,没有唤醒功能
	*P_IOA_Data = (0xffff&(~0x0010));
	

	*P_INT_Ctrl = ( 0x0004 | 0x0400 );				//IRQ5 2HZ AND IR2 timerB 
	//	*P_INT_Ctrl = 0x0400;						//只设置 IRQ2 TIMERB
	*P_TimerB_Data = 0xffff-0x0008;						//会自动重装
	*P_TimerB_Ctrl = C_4096Hz;
	
	__asm("int irq,fiq");
	
	while(1)
	{
		*P_Watchdog_Clear = 0x0001;

		if ( g_start_spk == true || g_start_realtime_spk == true ){
			//按键 重计算 但自动和手动报时不允许同步
			if ( g_start_realtime_spk == true && g_start_spk == false ){
				ComposeSpkArr();
			}
				
			for( i = 0; i <= g_spk_arr_idx; i++ )
				SPK( g_spk_arr[i] );
			
			//全部报时完毕才能开始新的一组
			g_start_spk = false;
			g_start_realtime_spk = false;
		}
		
		if ( g_vdc_enable ){
			////只设置一次
			if ( !g_vdc_set_parameter ){
				g_vdc_set_parameter = true;
				*P_ADC_MUX_Ctrl = C_ADC_CH6;
				*P_ADC_Ctrl = C_ADCE;
				uiData = *P_ADC_LINEIN_Data;
			}
			a = *P_ADC_Ctrl;
			b = *P_ADC_MUX_Ctrl;
			c = *P_ADC;
			d = *P_INT_Ctrl;
			VoltageADC();
		}
		else{
			//只设置一次
			if ( g_vdc_set_parameter ){
				g_vdc_set_parameter = false;
				
				*P_ADC_Ctrl = C_ADCN;
			}
		}
	}
}

__asm(".external F_FIQ_Service_SACM_A2000");
__asm(".external R_InterruptStatus");
__asm(".external G_INT_STATUS");
void FIQ(void)
{
	__asm("int off");
	__asm("[G_INT_STATUS] = R3");
	__asm("R3 = 0x0404");			//IRQ5 2HZ AND IR2 timerB 
	__asm("[R_InterruptStatus] = R3");
	__asm("R3 = [G_INT_STATUS]");
	__asm("int irq,fiq");

	if( *P_INT_Ctrl&0x2000 )
	{
		*P_INT_Clear = C_FIQ_TMA;
		__asm("call F_FIQ_Service_SACM_A2000");
	}
	else if ( *P_INT_Ctrl & 0x0004 )
	{
		*P_INT_Clear = 0x0004;
	}
	else if ( *P_INT_Ctrl & 0x0400 )
	{
		*P_INT_Clear = 0x0400;
	}
	else if( *P_INT_Ctrl&0x0800 )
	{
		*P_INT_Clear = C_FIQ_TMB;
	}
	else
		*P_INT_Clear = C_FIQ_PWM;
	
	/*
	__asm("int off");
	__asm("R3 = 0x0006"); 
	__asm("[0x702B] = R3");				//P_ADC_MUX_Ctrl C_ADC_CH6
	__asm("int irq,fiq");*/
}

void IRQ2(void)
{
	switch( g_led_index )
	{
	case 0:
		F_Show( g_led_index, g_led_sec_lo );
		g_led_index++;
		break;
	case 1:
		if ( g_led_min_hi != 0 ||
			g_led_min_lo!= 0 || 
			g_led_sec_hi != 0 ){
				F_Show( g_led_index, g_led_sec_hi );
			}
			g_led_index++;
			break;
	case 2:
			if ( !g_vdc_enable ){
				if ( g_led_min_hi != 0 || 
					g_led_min_lo != 0 ){
						F_Show( g_led_index, g_led_min_lo );
				}
			}
			else{//无论如何都加.
				F_Show( g_led_index, g_led_min_lo+10 );
			}
			g_led_index++;
			break;
	case 3:
		if( g_led_min_hi != 0 ){
			F_Show( g_led_index, g_led_min_hi );
		}
		g_led_index++;
		break;
	default:
		break;
	}
	
	if ( g_led_index > 3 ){
		g_led_index = 0;
	}
	
	//IOA4 为高电位
	if ( *P_IOA_Data & 0x0001){
		//计算按下键盘的持续时间
		if ( g_switch_timecount >= 0 )
			g_switch_timecount++;
			
		if ( g_switch_timecount >= MIN_SWITCH_TIME ){
			g_spk_time_count = 0;
			g_led_index = 0;
			//*P_IOA_Data &= ~(0x7f00);
			//停止转换计时
			g_switch_timecount = -1;
			
			//放在这里比较安全
			g_led_min_hi = 0;
			g_led_min_lo = 0;
			g_led_sec_hi = 0;
			g_led_sec_lo = 0;
			
			g_vdc_enable = !g_vdc_enable;
		}
	}
	else{//松开按键之后
		if ( g_switch_timecount > 0 &&
			g_switch_timecount <= MIN_REALSPK_TIME ){
			g_start_realtime_spk = true;
		}
		
		g_switch_timecount = 0;
	}
	
	if ( g_vdc_enable ){/*
		if (g_old_min_lo == g_led_min_lo &&
			g_old_min_hi == g_led_min_hi &&
			g_old_sec_hi == g_led_sec_hi ){//最后一位小数可能有跳动,这里不比较他如 1.25V
			
			if ( !g_already_spk_volage ){//没有自动报过电压,才开始计时
				g_volage_stbtime++;
			}
			
			if ( g_volage_stbtime >= MIN_VOLAGE_STBTIME ){
				g_volage_stbtime = 0;
			}
			
			g_start_realtime_spk = true;    //报告一次稳定的电压
			g_already_spk_volage = true;
		}
		else{
			g_volage_stbtime = 0;
			
			//前一次完全报告完成了才开始新的报告
			if (! g_start_realtime_spk )
				g_already_spk_volage = false;
			
			g_old_min_lo = g_led_min_lo;
			g_old_min_hi = g_led_min_hi;
			g_old_sec_lo = g_led_sec_lo;
			g_old_sec_hi = g_led_sec_hi;
		}*/	
	}
		
	*P_INT_Clear = 0x0400;	
}

void IRQ5(void)
{
	if(*P_INT_Ctrl & 0x0004  )
	{//IRQ5 2HZ
		__asm("int off");
		g_base_2HZ_count++;
		if( g_base_2HZ_count >= 2 )
		{
			g_base_2HZ_count = 0;
			
			if ( g_vdc_enable == false ){
				g_led_sec_lo++;
				if ( g_led_sec_lo >= 10 ){
					g_led_sec_lo = 0;
					g_led_sec_hi++;
					
					if ( g_led_sec_hi >= 6 ){
						g_led_sec_hi = 0;
						g_led_min_lo++;
						
						if ( g_led_min_lo >= 10 ){
							g_led_min_lo = 0;
							g_led_min_hi++;
							
							if ( g_led_min_hi >= 6 )
								g_led_min_hi = 0;
						}
					}
				}
				
				g_spk_time_count++;
				if ( g_spk_time_count >= SPK_TIME ){
					g_spk_time_count = 0;
					
					//准备一组新的报时数据 自动和手动报时不允许同步
					if ( g_start_spk == false && g_start_realtime_spk == false ){
						ComposeSpkArr();
						g_start_spk = true;
					}
				}
			}//g_vdc_enable==false
		}
		//必须清中断,否则会一直响应该中断
		 *P_INT_Clear = 0x0004;
		 
		 __asm("int irq,fiq");
	}
}

void VoltageADC(void)
{
	int i = 0;
	float fVoltage = 0;
	float x =0;
	float y = 0;
	unsigned long uiData = 0;
	
	for( i = 0; i < 16; i++ ){
		*P_Watchdog_Clear = 0x0001;
		uiData += AD();
	}
	uiData >>= 4;		//计算平均值
	fVoltage = (float)uiData/0xffc0*3.3;
	
	//显示如 3.91 的数字
	y = modff( fVoltage, &x );
	
	__asm("int off");
	if ( g_vdc_enable ){//屏蔽IRQ2中对min sec的修改
		g_led_min_hi = 0;			
		g_led_min_lo = (unsigned int)x;	;					//整数部分	
		g_led_sec_hi = (unsigned int)(y*100)/10;			//小数部分×100十位
		g_led_sec_lo = (unsigned int)(y*100)%10;			//小数部分×10取个位
	}
	__asm("int irq,fiq");	
}

unsigned int AD(void)
{
	unsigned int uiData = 0;
	while( !(*P_ADC_MUX_Ctrl&0x8000) );
	
	uiData = *P_ADC_LINEIN_Data;
	return(uiData&0xffc0);   //b0-b4
}

void ComposeSpkArr(void)
{
	__asm("int off");
	if ( g_vdc_enable ){
		//电压播报如: 嘀,二点一三
		g_spk_arr_idx = 0;
		g_spk_arr[g_spk_arr_idx] = SND_DI_BASE;
		
		/*只测一位
		if ( g_led_min_hi > 0 ){
			g_spk_arr_idx++;
			g_spk_arr[g_spk_arr_idx] = SND_NUM_BASE+g_led_min_hi;
			
			g_spk_arr_idx++;
			g_spk_arr[g_spk_arr_idx] = SND_NUM_BASE+10;
		}*/
		
		//不论如何 0 都要报
		if ( g_led_min_lo >= 0 ){
			g_spk_arr_idx++;
			g_spk_arr[g_spk_arr_idx] = SND_NUM_BASE+g_led_min_lo;
		}
		
		//无论如何加"."
		g_spk_arr_idx++;
		g_spk_arr[g_spk_arr_idx] = SND_POINT;
		
		if ( g_led_sec_hi >= 0 ){
			g_spk_arr_idx++;
			g_spk_arr[g_spk_arr_idx] = SND_NUM_BASE+g_led_sec_hi;
		}
		
		if ( g_led_sec_lo >= 0 ){
			g_spk_arr_idx++;
			g_spk_arr[g_spk_arr_idx] = SND_NUM_BASE+g_led_sec_lo;
		}
	}
	else{
		//嘀,现在时刻,21分20秒
		g_spk_arr_idx = 0;
		
		g_spk_arr[g_spk_arr_idx] = SND_DI_BASE;
		
		g_spk_arr_idx++;	
		g_spk_arr[g_spk_arr_idx] = SND_REP_BASE;
		
		if ( g_led_min_hi > 0 ){
			g_spk_arr_idx++;
			g_spk_arr[g_spk_arr_idx] = SND_NUM_BASE+g_led_min_hi;
			
			g_spk_arr_idx++;
			g_spk_arr[g_spk_arr_idx] = SND_NUM_BASE+10;
		}
		
		//不论如何 0 都不报
		if ( g_led_min_lo > 0 ){
			g_spk_arr_idx++;
			g_spk_arr[g_spk_arr_idx] = SND_NUM_BASE+g_led_min_lo;
		}
		
		//分
		if ( g_led_min_hi > 0 || g_led_min_lo > 0 ){
			g_spk_arr_idx++;
			g_spk_arr[g_spk_arr_idx] = SND_MIN;
		}
		
		if ( g_led_sec_hi > 0 ){
			g_spk_arr_idx++;
			g_spk_arr[g_spk_arr_idx] = SND_NUM_BASE+g_led_sec_hi;
			
			g_spk_arr_idx++;
			g_spk_arr[g_spk_arr_idx] = SND_NUM_BASE+10;
		}
		
		if ( g_led_sec_lo > 0 ){
			g_spk_arr_idx++;
			g_spk_arr[g_spk_arr_idx] = SND_NUM_BASE+g_led_sec_lo;
		}
		
		if ( g_led_sec_hi > 0 || g_led_sec_lo > 0 ){
			g_spk_arr_idx++;
			g_spk_arr[g_spk_arr_idx] = SND_SEC;
		}
	}
	__asm("int irq,fiq");
}


void SPK(unsigned int index)      
{  
	SACM_A2000_Initial(1);
	__asm("int off");
	//if ( *P_ADC_Ctrl & C_ADCE )
		*P_DAC_Ctrl = 0x00a0;
	__asm("int irq,fiq");
	SACM_A2000_Play( index, DAC1+DAC2, Ramp_UpDn_On );
	SACM_A2000_Volume(SPK_VOLUME);
	while( SACM_A2000_Status()&0x0001 )
	{			
		SACM_A2000_ServiceLoop();
		*P_Watchdog_Clear = 0x0001;
	}
	SACM_A2000_Stop();
}

⌨️ 快捷键说明

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