실제 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기능
누더기 코드의 전형적인 예.............
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기능
누더기 코드의 전형적인 예.............
- 전체 소스
#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 |