본문 바로가기

Enginius/Firmware

PIC32 - 기본 페리

 실제 eval b/d에서 테스트 한 것이 아니고, 디버거에서 시뮬레이션 한 것이기 때문에 확인 한 것은 타이머 인터럽트와 adc 인터럽트, oc(pwm)정도이다. 
 uart와 i2c에 문제가 있을 수 있으니 혹시 문제가 있는것을 발견한다면 알려주길!

 사용한 chip은 pic32mx5X 시리즈. usb type. 

 될 것으로 기대하는 기능
1. 3개의 타이머 (64us, 100us, 1000us)
2. 외부 인터럽트 
3. 시리얼 통신 (115200 BD)
4. 5개의 ADC
5. I2C 통신 (24LC0x)
6. 4개의 Input cpature
7. 5개의 PWM

 추가해야 하는 기능
1. spi 통신
2. usb기능
 
 누더기 코드의 전형적인 예.............
 
  1. 전체 소스 
 

#include 	/* PIC32 processor header file */
#include 	    /* peripheral library header file */

#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_1

#define SYS_FREQ (80000000L)

#define Uint16	unsigned int
#define Uc		unsigned char
#define Bool	unsigned char
#define True	1
#define False	0

unsigned int count = 0;
unsigned long tmr1cnt = 0, tmr4cnt = 0, tmr5cnt = 0;
unsigned int pwm1 = 0, pwm2 = 0, pwm3 = 0, pwm4 = 0, pwm5 = 0;
//#define DESIRED_BAUDRATE        (9600)      // The desired BaudRate
#define DESIRED_BAUDRATE        (115200)      // The desired BaudRate

//adc관련
unsigned int adc_value[16];
char adc_ready = 0;

//I2C 관련
#define PBCLK  (SYS_FREQ/2)
#define Fsck    50000
#define BRG_VAL     ((PBCLK/2/Fsck)-2)

#define EEPROM_ADDR	0xA0


//#define Nop() asm( "nop" )	//already defined



void i2c_wait(unsigned int cnt)
{
    while(--cnt)
    {
        Nop();
        Nop();
    }
}

Bool ReadMemory(Uint16 addr, Uc* data)
{
	// 메모리(24LC04B)는 512byte이다. (256*2 byte)
	// addr은 7bit이고	0b1010 000x가 0번 block
	//					0b1010 001x가 1번 block
	unsigned char i2cData[10], i2cSlaveAddr;
	int i2cSize = 0, i2cSend = 0;
	Uint16 i2cMemAddr;

	if(addr >= 0x200)
	{//에러 
		return False;
 	}
	else if(addr >= 0x100)
	{
		i2cSlaveAddr = EEPROM_ADDR | 0x02;
		i2cMemAddr = addr - 0x100;
	}
	else
	{
		i2cSlaveAddr = EEPROM_ADDR;
		i2cMemAddr = addr;
	}

	i2cData[0] = i2cSlaveAddr;
	i2cData[1] = (i2cMemAddr >> 8) & 0xFF;	//high addr
	i2cData[2] = i2cMemAddr & 0xFF;			//low addr 
	i2cSize = 3;

	StartI2C1();    //Send the Start Bit
	IdleI2C1();        //Wait to complete

    while( i2cSize )
	{
		MasterWriteI2C1( i2cData[i2cSend++] );
		IdleI2C1();        //Wait to complete

		i2cSize--;

		//ACKSTAT is 0 when slave acknowledge. if 1 then slave has not acknowledge the data.
		if( I2C1STATbits.ACKSTAT )
		{//에러?
			break;
		}
    }	
	//now send a start sequence again
	RestartI2C1();    //Send the Restart condition

	//wait for this bit to go back to zero
	IdleI2C1();    //Wait to complete
	
	MasterWriteI2C1( i2cSlaveAddr | 0x01 ); //transmit read command
	IdleI2C1();        //Wait to complete
	
    *data = MasterReadI2C1();

	StopI2C1();    //Send the Stop condition
	IdleI2C1();    //Wait to complete

	return True;
}

Bool WriteMemory(Uint16 addr, Uc data)
{
	// 메모리(24LC04B)는 512byte이다. (256*2 byte)
	// addr은 7bit이고	0b1010 000x가 0번 block
	//					0b1010 001x가 1번 block
	unsigned char i2cData[10], i2cSlaveAddr;
	int i2cSize = 0, i2cSend = 0;
	Uint16 i2cMemAddr;
	
	if(addr >= 0x200)
	{//에러 
		return False;
 	}
	else if(addr >= 0x100)
	{
		i2cSlaveAddr = EEPROM_ADDR | 0x02;
		i2cMemAddr = addr - 0x100;
	}
	else
	{
		i2cSlaveAddr = EEPROM_ADDR;
		i2cMemAddr = addr;
	}

	i2cData[0] = i2cSlaveAddr;
	i2cData[1] = (i2cMemAddr >> 8) & 0xFF;	//high addr
	i2cData[2] = i2cMemAddr & 0xFF;			//low addr
	i2cData[3] = data;
	i2cSize = 4;
	
	StartI2C1();	//send start bit
	IdleI2C1();		//wait ACK
	
	while(i2cSize)
	{
		MasterWriteI2C1( i2cData[i2cSend++] );
		IdleI2C1();
		i2cSize--;
		
		if( I2C1STATbits.ACKSTAT )
		{//에러 ?
			break;
		}
	}
	StopI2C1();    //Send the Stop condition
    IdleI2C1();    //Wait to complete
	
	// 이 뒤의 루틴이 필요한가? 
    while(1)
    {
		i2c_wait(10);

		StartI2C1();    //Send the Start Bit
		IdleI2C1();        //Wait to complete

		MasterWriteI2C1( i2cData[0] );
		IdleI2C1();        //Wait to complete

		if( I2C1STATbits.ACKSTAT == 0 )    //eeprom has acknowledged
		{
			StopI2C1();    //Send the Stop condition
			IdleI2C1();    //Wait to complete
			break;
		}

		StopI2C1();    //Send the Stop conditions
		IdleI2C1();    //Wait to complete
    }


	return True;
}



//UART 관련 
// helper functions
void WriteString(const char *string)
{
    while(*string != '\0')
    {
        while(!UARTTransmitterIsReady(UART2))
            ;

        UARTSendDataByte(UART2, *string);

        string++;

        while(!UARTTransmissionHasCompleted(UART2))
            ;
    }
}
void PutCharacter(const char character)
{
        while(!UARTTransmitterIsReady(UART2))
            ;

        UARTSendDataByte(UART2, character);


        while(!UARTTransmissionHasCompleted(UART2))
            ;
}

int main(void)
{
// Optimization Macro를 사용하여 최적의 성능이 되도록 설정 
	int    pbClk;

	//시스템 초기화 - 80MHz
	pbClk=SYSTEMConfigPerformance(SYS_FREQ);
	//타이머 인터럽트 초기화 (64us, 100us, 1000us)
	//타이머 1 초기화 
	OpenTimer1(T1_ON|T1_IDLE_CON |T1_PS_1_8 , 640);
	OpenTimer4(T4_ON|T4_IDLE_CON |T4_PS_1_8 , 1000);
	OpenTimer5(T5_ON|T5_IDLE_CON |T5_PS_1_8 , 10000);	
	mT1IntEnable(1);
	mT4IntEnable(1);
	mT5IntEnable(1);;
	mT1SetIntPriority(3);
	mT4SetIntPriority(3);
	mT5SetIntPriority(3);
	INTEnableSystemMultiVectoredInt();	
	
	//외부 인터럽트 초기화	
	mPORTFSetPinsDigitalIn((BIT_6 ));   
	mINT0ClearIntFlag();       
	mINT0IntEnable(1);
	mINT0SetIntPriority(3);
	mINT0SetEdgeMode(0);//Falling Edge
		
	//시리얼 통신, 인터럽트 초기화
	OpenUART2(UART_EN, UART_RX_ENABLE | UART_TX_ENABLE, pbClk/16/DESIRED_BAUDRATE-1);    // calculate actual BAUD generate value.
	INTEnable(INT_UART2,INT_ENABLED);
	INTSetVectorPriority(INT_UART2,INT_PRIORITY_LEVEL_3);
	//mUART2IntEnable(1);
	//mU2SetIntPriority(3);
	
	//I2C 통신 초기화
	OpenI2C1( I2C_EN, BRG_VAL );


//*	//ADC 초기화
	CloseADC10();

	// Turn module on | ouput in integer | trigger mode auto | enable autosample
	#define PARAM1	ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON
	// ADC ref external | disable offset test | enable scan mode | perform 16 samples
	#define PARAM2	ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_16 | ADC_ALT_BUF_OFF| ADC_ALT_INPUT_OFF
	// use ADC internal clock | set sample time
	//#define PARAM3	ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15
	//#define PARAM4	ENABLE_ALL_ANA
	//#define PARAM5	SKIP_SCAN_ALL
	#define PARAM3	ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_12
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA
	#define PARAM5	SKIP_SCAN_AN5 | SKIP_SCAN_AN6 | SKIP_SCAN_AN7 | SKIP_SCAN_AN8 | SKIP_SCAN_AN9 | SKIP_SCAN_AN10 | SKIP_SCAN_AN11 | SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15 

	// use ground as neg ref for A
	SetChanADC10( ADC_CH0_NEG_SAMPLEA_NVREF);
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above
	ConfigIntADC10(ADC_INT_ON | ADC_INT_PRI_3);
	EnableADC10();
//*/	
	//Input capture 인터럽트 초기화
	OpenTimer3(T3_ON | T3_PS_1_256, 0xffff);
    // Enable Input Capture Module 1 - RD8
    // - Capture Every edge
    // - Enable capture interrupts
    // - Use Timer 3 source
    // - Capture rising edge first
	OpenCapture1( IC_EVERY_EDGE | IC_INT_1CAPTURE | IC_TIMER3_SRC | IC_FEDGE_RISE | IC_ON );
	mIC1IntEnable(1);
	mIC1SetIntPriority(3);

	OpenCapture2( IC_EVERY_EDGE | IC_INT_1CAPTURE | IC_TIMER3_SRC | IC_FEDGE_RISE | IC_ON );
	mIC2IntEnable(1);
	mIC2SetIntPriority(3);

	OpenCapture3( IC_EVERY_EDGE | IC_INT_1CAPTURE | IC_TIMER3_SRC | IC_FEDGE_RISE | IC_ON );
	mIC3IntEnable(1);
	mIC3SetIntPriority(3);

	OpenCapture4( IC_EVERY_EDGE | IC_INT_1CAPTURE | IC_TIMER3_SRC | IC_FEDGE_RISE | IC_ON );
	mIC4IntEnable(1);
	mIC4SetIntPriority(3);
	



	//PWM 초기화 (Output capture) 5개	
	PORTSetPinsDigitalOut(IOPORT_D, BIT_0|BIT_1|BIT_2|BIT_3|BIT_4);
	#define PERIOD 1000
	OpenTimer2(T2_ON|T2_IDLE_CON |T2_PS_1_1 , PERIOD);
	OpenOC1 (OC_ON|OC_TIMER_MODE16|OC_PWM_FAULT_PIN_DISABLE ,0x0000, pwm1);
	OpenOC2 (OC_ON|OC_TIMER_MODE16|OC_PWM_FAULT_PIN_DISABLE ,0x0000, pwm2);
	OpenOC3 (OC_ON|OC_TIMER_MODE16|OC_PWM_FAULT_PIN_DISABLE ,0x0000, pwm3);
	OpenOC4 (OC_ON|OC_TIMER_MODE16|OC_PWM_FAULT_PIN_DISABLE ,0x0000, pwm4);
	OpenOC5 (OC_ON|OC_TIMER_MODE16|OC_PWM_FAULT_PIN_DISABLE ,0x0000, pwm5);
				
	//테스트를 위한 토글용 비트 
	mPORTCSetPinsDigitalOut((BIT_1 ));   
	mPORTASetPinsDigitalOut((BIT_7 )); 





	while(1)
	{
		//adc받기
		if(adc_ready)
		{
			adc_ready = 0;
			adc_value[0] = adc_value[0];
			adc_value[1] = adc_value[1];
			adc_value[2] = adc_value[2];
			adc_value[3] = adc_value[3];
			adc_value[4] = adc_value[4];
		}
		

		
		//pwm 출력하기 	//1001이 maximum
		SetDCOC1PWM(pwm1);	
		SetDCOC2PWM(pwm2);
		SetDCOC3PWM(pwm3);
		SetDCOC4PWM(pwm4);
		SetDCOC5PWM(pwm5);	

	}

}
 

//외부 인터럽트 루틴
void __ISR(_EXTERNAL_0_VECTOR,ipl3) _extint0(void)
{
	mINT0ClearIntFlag();
}    
	
//64us 타이머 인터럽트 루틴 
void __ISR(_TIMER_1_VECTOR,ipl3) _t1(void) 
{
	mT1ClearIntFlag();
	tmr1cnt++;
}	

//100us 타이머 인터럽트 루틴 
void __ISR(_TIMER_4_VECTOR,ipl3) _t4(void) 
{
	mT4ClearIntFlag();
	tmr4cnt++;

	mPORTCToggleBits(BIT_1);
}	

//1000us 타이머 인터럽트 루틴 
void __ISR(_TIMER_5_VECTOR,ipl3) _t5(void) 
{
	mT5ClearIntFlag();
	tmr5cnt++;

	pwm1 = 1000;
	pwm2 = 800;
	pwm3 = 600;
	pwm4 = 400;
	pwm5 = 200;

}

//UART 인터럽트
void __ISR(_UART2_VECTOR,ipl3) _uart2(void) 
{
	// Is this an RX interrupt?
	if(INTGetFlag(INT_SOURCE_UART_RX(UART2)))
	{
		// Clear the RX interrupt Flag
	    INTClearFlag(INT_SOURCE_UART_RX(UART2));

		// Echo what we just received.
		PutCharacter(UARTGetDataByte(UART2));
		

	}

	// We don't care about TX interrupt
	if ( INTGetFlag(INT_SOURCE_UART_TX(UART2)) )
	{
		INTClearFlag(INT_SOURCE_UART_TX(UART2));
	}
}

//Input Capture 인터럽트 1 
void __ISR(_INPUT_CAPTURE_1_VECTOR,ipl3) _ic1(void) 
{
	mIC1ClearIntFlag();
}

//Input Capture 인터럽트 2
void __ISR(_INPUT_CAPTURE_2_VECTOR,ipl3) _ic2(void) 
{
	mIC2ClearIntFlag();
}

//Input Capture 인터럽트 3
void __ISR(_INPUT_CAPTURE_3_VECTOR,ipl3) _ic3(void) 
{
	mIC3ClearIntFlag();
}

//Input Capture 인터럽트 4
void __ISR(_INPUT_CAPTURE_4_VECTOR,ipl3) _ic4(void) 
{
	mIC4ClearIntFlag();
}

void __ISR(_ADC_VECTOR, ipl3) ADC10Handler(void)
{
	char z = 0;
	for (z=0; z < 5; z++)
	{
		adc_value[z] = ReadADC10(z);
	}
	adc_ready = 1;
	
	mPORTAToggleBits(BIT_7);

	mAD1ClearIntFlag();
} 

'Enginius > Firmware' 카테고리의 다른 글

PIC32 - GPIO  (0) 2010.02.17
PIC32 - Interrupt  (0) 2010.02.17
PIC32 - ADC  (0) 2010.02.17
AVR - atmega128 pwm 쓰기  (0) 2010.01.01
AVR - LDM (Led DotMatrix)  (0) 2009.11.19