zia.newversion
Member level 5
PIC16F887 Code Compiled with HI-TECH C Compiler from PIC16 - Cannot catch INT
Hi there... I was experimenting with the 887 µC, and to test myself, I tried to play with the A2D converter. It could be done in a very simple manner, but I thought it'd be good to do it through interrupts. This program is supposed to take a sample on AN0 every 1 second and calculate a running average of last 8 samples.
For that, I programmed the timer to generate an interrupt every 128µs and at every INT (if it is indeed a TMR0 INT), a counter will be incremented. After the counter has passed 7812 (which would mean 1 second has passed), it'd call the AD conversion routine which is supposed to send the GO signal to AD converter module. After that the current interrupt service ends. The program resumes normal execution until the A2D-Conversion Complete interrupt arrives (which happens within 4µs or 8 instruction cycles after the TMR0 INT has triggered the A2D conversion).
I hope you are with me until here. Right... So, after the conversion is complete, another INT is generated and the ISR processed the interrupt (but this time it doesn't qualify for a TMR0 interrupt, but a AD interrupt instead). So the program goes on and takes the AD result and puts it into an array of 8 values (which is basically a stack for last 8 AD results) then calculates the average and then converts the final result to it's decimal equivalent. then every decimal place to its BCD equivalent and then sends it to the appropriate nibble of the each of PORTB and PORTC.
Here is the code, if you will:
I commented so it'd be documented and I wouldn't forget what piece of code does what. I guess these comments shall help you understand the code as well.
Now here is the problem:
I used Proteus ISIS to build the circuit and loaded the program. But the code 7-segment displays keep displaying 0000... I tried to investigate and loaded the program in MPLAB SIM, then executed the "Animate" command, to watch where it's going... After an awful lot of time, I came to know that it keeps sleeping. It is stuck in the SLEEP() macro and interrupt never comes!
I guess I must have done some mistakes in the conversion and display code as well, but how'd I know if it doesn't get into the interrupt and starts executing instructions other then SLEEP...
As far as I could proof-read, my code sees alright. Could someone else, who has worked with HI-TECH compiler before, help me out there? I shall be duly grateful.
PS. I have attached the ZIP archive containing the MPLAB Project, C Code file and Proteus DSN file.
Hi there... I was experimenting with the 887 µC, and to test myself, I tried to play with the A2D converter. It could be done in a very simple manner, but I thought it'd be good to do it through interrupts. This program is supposed to take a sample on AN0 every 1 second and calculate a running average of last 8 samples.
For that, I programmed the timer to generate an interrupt every 128µs and at every INT (if it is indeed a TMR0 INT), a counter will be incremented. After the counter has passed 7812 (which would mean 1 second has passed), it'd call the AD conversion routine which is supposed to send the GO signal to AD converter module. After that the current interrupt service ends. The program resumes normal execution until the A2D-Conversion Complete interrupt arrives (which happens within 4µs or 8 instruction cycles after the TMR0 INT has triggered the A2D conversion).
I hope you are with me until here. Right... So, after the conversion is complete, another INT is generated and the ISR processed the interrupt (but this time it doesn't qualify for a TMR0 interrupt, but a AD interrupt instead). So the program goes on and takes the AD result and puts it into an array of 8 values (which is basically a stack for last 8 AD results) then calculates the average and then converts the final result to it's decimal equivalent. then every decimal place to its BCD equivalent and then sends it to the appropriate nibble of the each of PORTB and PORTC.
Here is the code, if you will:
Code C - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 // FOSC=8MHz #include <htc.h> __CONFIG(0x23C0); __CONFIG(0x3EFF); void ISR_TMR0(); void ISR_ADCONV(); void interrupt ISR(); void StartADConv(); void Out(); const double REZ = 0.004887585533; //5V/1023 unsigned int COUNT = 0x00; unsigned int ADRES = 0x00; unsigned int AVG = 0x00; unsigned int READING[8] = {0,0,0,0,0,0,0,0}; void main() { TRISA = 0x01; // PORTA is OP TRISB = 0x00; // PORTB is OP TRISC = 0x00; // PORTC is OP TRISD = 0x00; // PORTD is OP TRISE = 0x00; // PORTE is OP PORTA = 0x00; // Clear PORTA PORTB = 0x00; // Clear PORTB PORTC = 0x00; // Clear PORTC PORTD = 0x00; // Clear PORTD PORTE = 0x00; // Clear PORTE ANSEL = 0x01; // RA0/AN0 as analog ANSELH = 0x00; // Everything else is digital OPTION = 0x41; // 1:4 Prescalar assigned to TMR0 ADCON0 = 0x80; // ADCON Freq = FOSC/32 PEIE = 1; // Peripheral INT enabled T0IE = 1; // TMR0 INT enabled ADIE = 1; // ADCON INT enabled ADFM = 1; // ADCON format right justified ei(); // Enable the interrupts while(1) SLEEP(); // Sleep untill interrupt arrives } void interrupt ISR() { if(T0IF) // If INT was caused by TMR0 ISR_TMR0(); // Call TMR0 INT module else if(ADIF) // If INT was caused by ADCON ISR_ADCONV(); // Call ADCONV INT module Out(); // Whether or not if was successful // --- do call the output module return; // Get the f*** outta here } void ISR_TMR0() { COUNT++; // Increment the counter if(COUNT>7812) // 0.5us x 256 x 7812 ~= 1s StartADConv(); // If 1s passed, start conv. T0IF = 0; // Don't forget to clear INT flag return; // Get the f*** outta here } void StartADConv() { ADON = 1; // Turn AD mod ON GODONE = 1; // Start conversion return; } void ISR_ADCONV() { ADRES = (ADRESH * 0x100) + ADRESL; // Combine result chars to form int unsigned char i; for (i=7; i>0; i--) // Stack up last 7 readings { READING[i] = READING[i-1]; } READING[0] = ADRES; // Put latest reading to 8th unsigned int s; s = 0; for (i=7; i>=0; i--) // Sum all readings { s = s + READING[i]; } AVG = s/0x08; // Divide sum by 8 } void Out() { unsigned int Op = AVG*REZ*1000; // Convert ADC reading to corresponding // --- analog value and make it an int unsigned char D1 = Op/1000; // Place before decimal Op = Op%1000; unsigned char D2 = Op/100; // Place after decimal Op = Op%100; unsigned char D3 = Op/10; // 2 places after decimal unsigned char D4 = Op%10; // 3 places after decimal PORTB = D1; // D1 on first nibble of PORTB PORTB = PORTB+D2*0x10; // D2 on second nibble of PORTB PORTC = D3; // D3 on first nibble of PORTC PORTC = PORTC+D3*0x10; // D4 on first nibble of PORTC }
I commented so it'd be documented and I wouldn't forget what piece of code does what. I guess these comments shall help you understand the code as well.
Now here is the problem:
I used Proteus ISIS to build the circuit and loaded the program. But the code 7-segment displays keep displaying 0000... I tried to investigate and loaded the program in MPLAB SIM, then executed the "Animate" command, to watch where it's going... After an awful lot of time, I came to know that it keeps sleeping. It is stuck in the SLEEP() macro and interrupt never comes!
I guess I must have done some mistakes in the conversion and display code as well, but how'd I know if it doesn't get into the interrupt and starts executing instructions other then SLEEP...
As far as I could proof-read, my code sees alright. Could someone else, who has worked with HI-TECH compiler before, help me out there? I shall be duly grateful.
PS. I have attached the ZIP archive containing the MPLAB Project, C Code file and Proteus DSN file.
Attachments
Last edited: