Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Probably a simple problem - for loop led flasher

Status
Not open for further replies.
I'm currently learning how to program in C, with limited experience in assembly and BASIC. I've read some stuff on syntax etc and uploaded example code to my PK1, which works fine, but it doesn't make much sense to me. So I thought to understand the programming better, write the program from scratch to simply flash an led and go from there, ultimately to make a PIC based CAN to serial converter.

It appears to compile and program without errors, which suggests there is something wrong with the code. The led between RA4 and RA5 is half on. But I can't see the problem(s) comparing this with example code from others. Also is there a list of good practice techniques or simply cut and paste code from others (without really understanding?)

Code:
/*

*/

#include <pic.h>


__CONFIG(FCMDIS & IESODIS & BORDIS & UNPROTECT & UNPROTECT & MCLREN & PWRTDIS & WDTDIS & INTCLK);

//Define Variables

int i,j;

void init_device(void) 
{
	PORTA = 0x00;	//Clear PORTA
	CMCON0 = 0x07;	//Comparators off. Digital I/O Enable
	ANSEL = 0x00;	//ADC Disable
	TRISA = 0x0F;	//Set TRISA as Outputs
	INTCON = 0;		//Interrupts Disabled

}

void main(void)
{
	init_device();
		while(1) //Loop Forever
	{

	for (i = 0; i < 200; i++)  //  Simple Delay
    	for (j = 0; j < 150; j++);
					
			RA4 = 1;                //D0 On

    for (i = 0; i < 200; i++)  //  Simple Delay
        for (j = 0; j < 150; j++);
        			
			RA4 = 0;                //D0 Off
	}
}

The PIC is a 16F688 ( so I can get the RS232 part working later) in MPLAB 8.5 with Hi-Tech compiler
 
Last edited:
Code:
TRISA = 0x0F;	//Set TRISA as Outputs

I believe setting tris bits high configures pins as inputs rather then outputs. Set TRISA to 0x00 to make all pins outputs. You also need to switch to memory bank 1 in order to be able to address the TRIS registers - i don't know if your compiler does this automatically. If it does not you need to do this yourself.
 
Last edited:
I thought that's what I'd done, I'm trying to get RA4 and RA5 to be outputs. The TRISA register is;

[X,X,RA5,RA4,RA3,RA2,RA1,RA0]

So setting TRISA to 0x0F means 0b00001111 or am I not understanding this?

D0 led is half on like I might have blown the PIC?
 
Okay, i didnt see that you were using RA4 & RA5.
Can you post the generated assembly code?
 
Things look ok, I'm assuming when you say it looks "half on" it's because the LED is actually blinking on and off, but it's just doing so very very fast, thus it looks to be partially on. You could look to increase your delay times and see if this has an effect, though it looks like you're using the internal clock, so you should see the same speeds as the original coder did. Don't have my stuff with me at work or I'd try this out for you.
 
Well, I'm simulating approx. 226ms between the LED going from on to off and vice-versa. 453ms from on to on, or off to off...meaning the LED is switching more than twice a second but should still be visible blinking. Assuming it's all running at 8MHz internal clock speeds, which your config word seems to indicate, but I dunno if you change those config word settings with your programmer and have an external crystal attached or not, assuming not.
 
The compiler might optimize the delay's out if it's smart enough too see the loops do nothing.
Also , does the compiler automatically add the required bank switching code or not ?

A look at the generated assembler code would clear things up.
 
This was bugging me so I went ahead and set it up in proteus. Noticed that RA4 wasn't acting as expected, looked at your config word. You have it set to INTCLK which has the internal clock output on RA4, you want to change this to INTIO so you use the internal clock but have RA4 as an IO pin. Proteus shows this blinking once I made that change:
__CONFIG(FCMDIS & IESODIS & BORDIS & UNPROTECT & UNPROTECT & MCLREN & PWRTDIS & WDTDIS & INTIO);
 
Changing the __CONFIG bit got it flashing at about 2Hz. I guess the LED was flashing at 8MHz which is why it looked half on. Wonderful, thanks Norlin. I have also heard of a good compiler optimizing out wasteful for loop delays but I guess this one didn't do that - good suggestion though for the future. Next will be getting the EUSART working to send an ASCII character to the PC's hyperterm, shouldn't be too hard, right?

I've got the EUSART working on this PIC before with assembly, but will need to research it a bit more to do it in C. Is there a way of converting easily from assembly to C or is that completely pointless as C is a higher level language?

Code:
;**********************************************************************
;   This file is a basic code template for object module code         *
;   generation on the PICmicro PIC16F688. This file contains the      *
;   basic code building blocks to build upon.  As a project minimum   *
;   the 16F688.lkr file will also be required for this file to        *
;   correctly build. The .lkr files are located in the MPLAB          *
;   directory.                                                        *
;                                                                     *
;   If interrupts are not used all code presented between the         *
;   code section "INT_VECTOR and code section "MAIN" can be removed.  *
;   In addition the variable assignments for 'w_temp' and             *
;   'status_temp' can be removed.                                     *
;                                                                     *
;   If interrupts are used, as in this template file, the 16F688.lkr  *
;   file will need to be modified as follows: Remove the lines        *
;     CODEPAGE   NAME=vectors  START=0x0      END=0x4      PROTECTED  *
;   and                                                               *
;     SECTION    NAME=STARTUP  ROM=vectors                            *
;   and change the start address of the page0 section from 0x5 to 0x0 *
;                                                                     *
;   Refer to the MPASM User's Guide for additional information on     *
;   features of the assembler and linker (Document DS33014).          *
;                                                                     *
;   Refer to the respective PICmicro data sheet for additional        *
;   information on the instruction set.                               *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Filename: Flashing LED1.asm                                      *
;    Date: 2009/04/20                                                 *
;    File Version: 1.0                                                *
;                                                                     *
;    Author: Jules Lewarne                                            *
;    Company:                                                         *
;                                                                     *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Files required:                                                  *
;                    16F688.lkr                                       *
;                                                                     *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Notes:                                                           *
;                                                                     *
;                                                                     *
;                                                                     *
;                                                                     *
;**********************************************************************

	list      p=16F688           	; list directive to define processor
	#include <p16F688.inc>        	; processor specific variable definitions

	errorlevel  -302              	; suppress message 302 from list file

; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file.
; See data sheet for additional information on configuration word settings.

	__CONFIG    _CP_OFF & _CPD_OFF & _BOD_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _FCMEN_OFF & _IESO_OFF



;***** VARIABLE DEFINITIONS 

; FORMAT: [name]	RES	[number of bytes reserved]
INT_VAR		UDATA_SHR	0x71   
DVAR		RES 1
DVAR2		RES 1
DVAR3		RES 1
ADC_RESULT	RES 1


;**********************************************************************
RESET_VECTOR	CODE	0x000		; processor reset vector
		goto    Main            ; go to beginning of program


INT_VECTOR	CODE	0x004		; interrupt vector location
		retfie                  ; return from interrupt

;**********************************************************************
;	Function Name: MAIN
;	
;	Parameters:
;
;	Description: This is the main program which is executed once the processor
;		has powered up.
;		The code within this routine performs some device initialisation then
;		flashes an LED. This routine makes use of another routine which causes
;		a short delay by sending the processor into a loop which decrements from
;		an arbitrary value until it reaches zero.
;**********************************************************************

Main
		
		;		
		
		
		;Device Initialisation
		
        bsf     STATUS,RP0  ; set file register bank to 1
        bsf    	ANSEL, 0       ; switch on ADC on AN0
        movlw	B'01110000'	; Set Conversion Clock frequency - xx11xxxx = internal clock
        movwf	ADCON1
        movlw   B'11001111' ; Set Ports to I/O, TRISA register: [X][X][RA5][RA4][RA3][RA2][RA1][RA0]
        movwf   TRISA    	;									Don't  I/O	I/O	  I	  I/O  I/O  I/O
							; 1 = input, 0 = Output				Care    
							
		
        bcf     STATUS,RP0  ; set file register bank to 0

        movlw   B'00000111' ; switch off the comparator, enable digital i/o
        movwf   CMCON0      ;
        
        movlw	B'00000001'	; Enable ADC, left justify, Vdd ref, AN0 input,
		movwf	ADCON0		; 
		
		clrf PORTA ; Set all PORTA outputs to zero
					
;**********************************************************************************
;						EUSART Setup
;**********************************************************************************
	
		bsf		TXSTA, TXEN 	; Enable EUSART
		bcf		TXSTA, SYNC 	; Disable synchronous communication
		bsf		TXSTA, BRGH 	; Select Baud Rate Generator high range
		bsf		RCSTA, SPEN 	; Serial Port Enable
		bcf		BAUDCTL, BRG16	; 16 bit baud rate generator disabled
		movlw	B'00011001' ; setup baudrate generator
		movwf	SPBRG

Loop  
		;btfsc PORTA, 3 ; Wait for button on RA3
        ;goto Loop

				; PORTA register: [X][X][RA5][RA4][RA3][RA2][RA1][RA0]
     			;				   Don't  I/O	I/O	  I	  I/O  I/O  I/O
				;				   Care    
				;						   D0/D1   D2/D3  D6/D7
				;						  o-!>!-o---!>!--o-!>!-o
				;						  o-!<!-o---!<!--o-!<!-o
				;							   D4/D5
				;						  o-----!>!------o
				;						  o-----!<!------o


		;movlw B'00010000' ; PORTA Register
		;movwf PORTA

;**********************************************************************************	
;							Flash the LED
;**********************************************************************************

		bsf 	PORTA,4 ; set BIT 4 of PORTA to one
		call 	Delay
		bcf 	PORTA,4 ; set BIT 4 of PORTA to zero
		call 	Delay
		;bsf		PORTA,5 ; set BIT 5 of PORTA to one
		;call	Delay
		;bcf		PORTA,5 ; set BIT 5 of PORTA to zero
		;call	Delay
		;call	Delay
		;call	Delay

;**********************************************************************************
;							EUSART Transmission Test
;**********************************************************************************
		
		;movlw	0x41 ; = 'A' in ASCII
	;	movwf	TXREG
	;	call 	Delay
	;	movlw 	0x42 ; = 'B' in ASCII
	;	movwf	TXREG
	;	call	Delay
	;	movlw	0x43 ; = 'C' in ASCII
	;	movwf	TXREG
	;	call	Delay
		
;**********************************************************************************
;							Analogue to Digital Conversion
;**********************************************************************************		

		bsf		ADCON0, GO	; Start conversion
ADCTEST	btfsc	ADCON0, GO	; Is conversion done?
		goto	ADCTEST		; 	No, Test again
		bcf     STATUS,RP0  ; set file register bank to 0
		movf	ADRESH, W	; read upper 8 bits (Most significant bits)
		movwf	ADC_RESULT	; Place conversion into ADC_RESULT register
		movf	ADC_RESULT, W
		movwf	TXREG		; Send A/D Conversion on serial port
				
		
		
Goto Loop
;**********************************************************************************
;							Delay Subroutine
;**********************************************************************************
Delay
    	movlw		0xff	; set outer delay loop (change these hex number to change the frequency)
    	movwf		DVAR2	; memory location
Delay0
    	movlw		0xff	; set inner delay loop  (change these hex number to change the frequency)
    	movwf		DVAR	; incremental memory
 							; location
Delay1	decfsz		DVAR,1
		goto		Delay1
    	decfsz		DVAR2,1
    	goto		Delay0
		
    	return



; initialize eeprom locations

EE		CODE	0x2100
		DE	0x00, 0x01, 0x02, 0x03


		END                       ; directive 'end of program'

This is what I have so far:

Code:
/*


*/

#include <htc.h>

//Define Variables:

int i, j;

__CONFIG(FCMDIS & IESODIS & BORDIS & UNPROTECT & UNPROTECT & MCLREN & PWRTDIS & WDTDIS & INTIO);

void init_comms(void) {
	PORTA = 0x30;	//Initialise PortA RA4 and RA5
	PORTC = 0x30;	//Initialize PortC, RC5 and RC4
	CMCON0 = 0x07;	//Comparators off. Digital I/O	
	ANSEL = 0x00;	//ADC Disable
	TRISA = 0x0F;	//Set RA4 and RA5 to outputs	
	TRISC = 0x20;	//Set RC5 as an Input, RC4 to an Output

	//Desired Baud Rate = 9600, Fosc = 4MHz
	//Fosc/[16(n+1)] = Desired Baud Rate; where n = SPBRG
	SPBRG = 25;	//Set baud rate to 9600
	BRG16 = 0;	//8-bit Baud Rate Generator is used
	BRGH  = 1;	//High speed
	SYNC  = 0;	//Asynchronous mode
	TXEN  = 1;	//Transmit enabled
	SPEN  = 1;	//Serial port enabled
	CREN  = 1;	//Enables receiver
	RX9   = 0;	//Selects 8-bit reception
	TX9   = 0;	//Selects 8-bit transmission
	RCIE  = 0;		
	TXIE  = 0;	//Disables tx interrupts
	PEIE  = 0;	//Disables interrupts for CPU 		
}

void putch(unsigned char byte)
{
	//output 1 byte
	while(!TXIF)	//set when register is empty
		continue;
	TXREG = byte;
}

void main(void) 
{ 
	INTCON = 0;
	init_comms();
        while(1) 
        {
	    putch('a');
		putch('b');
		putch('c');
		
		for (i = 0; i < 200; i++)  //  Simple Delay
    	for (j = 0; j < 150; j++);
					
			RA4 = 1;                //D0 On

    	for (i = 0; i < 200; i++)  //  Simple Delay
        for (j = 0; j < 150; j++);
        			
			RA4 = 0;                //D0 Off
        }
}

My plan is two fold - design a CAN to Serial 'bridge' for a project at work and design a simple data logger to simply send analogue readings of voltages and currents to a LabView program on my PC.
 
Last edited:
Now I'm trying to get the ADC part working but there are some errors I can't see where the problem is. I am trying to make the PIC do what I had it doing before where it takes a sample from AN0 and puts it in the TXREG to be transmitted to the PC. I would think it should be less lines in C than I had before in assembly.

the errors are:

Error [314] C:\Users\Documents\C Programming\Serial Interface\Main.c; 53.1 ";" expected
Error [192] C:\Users\Documents\C Programming\Serial Interface\Main.c; 57.9 undefined identifier "byte"

Code:
/*


*/

#include <htc.h>


__CONFIG(FCMDIS & IESODIS & BORDIS & UNPROTECT & UNPROTECT & MCLREN & PWRTDIS & WDTDIS & INTIO);

//Define Variables
int i,j;
int dlay = 63;
//unsigned char ADC_1, ADC_2
int ADCValue = 0;
//unsigned char byte

void init_comms(void) {
	CMCON0 = 0x07;	//Comparators off. Digital I/O
	PORTA = 0x00;	//Initialise PortA, RA4 and RA5 
	PORTC = 0x30;	//Initialize PortC, RC5 and RC4
	TRISA = 0x00;	//Set RA4 and RA5 as outputs
	TRISC = 0x20;	//Set RC5 as an Input, RC4 to an Output

	//Desired Baud Rate = 9600, Fosc = 4MHz
	//Fosc/[16(n+1)] = Desired Baud Rate; where n = SPBRG
	SPBRG = 25;	//Set baud rate to 9600
	BRG16 = 0;	//8-bit Baud Rate Generator is used
	BRGH  = 1;	//High speed
	SYNC  = 0;	//Asynchronous mode
	TXEN  = 1;	//Transmit enabled
	SPEN  = 1;	//Serial port enabled
	CREN  = 1;	//Enables receiver
	RX9   = 0;	//Selects 8-bit reception
	TX9   = 0;	//Selects 8-bit transmission
	RCIE  = 0;	//Disables rx interrupts	
	TXIE  = 0;	//Disables tx interrupts
	PEIE  = 0;	//Disables interrupts for CPU

/*	//ADC Initialize
	ANSEL = 0x01;	//Set AN0 as ADC Input
	ADCON0 = 0x01;	//Turn on ADC
					//Bit 7 - Left justified
					//Bit 6 - Use Vdd as ref.
					//Bit 4:2 - Channel 0
					//Bit 1 - Do not start
					//Bit 0 - Turn on ADC
	ADCON1 = 0x10;	//Select the clock Fosc/8

}
*/
void putch(unsigned char byte)
{
	//output 1 byte
	while(!TXIF)	//set when register is empty
		continue;
	TXREG = byte;
}
//return

/*void ADCcon(void)
{
	ADCON0 = 0x02;
	if(!GODONE);
	{
	ADCValue = ADRESH;	
	}	
	
}
*/
void main(void) 
{ 
	INTCON = 0;
	init_comms();
        while(1) 
        {
			for (i = 0; i < 255; i++);
			{
				for (j = 0; j < dlay; j++)
				{
				PORTA = 0x20;
	    		//putch('a');
				}
			}
				PORTA = 0x00;
        }
}

I've tried defining the unsigned char byte but that causes more errors about conflicting declarations. Please help again, it's probably another simple omission.
 
Last edited:
You commented out the closing bracket "}" for the function init_comms(void).
everything between /* and */ is considered comment.
 
Ok, Cleared that error, it compiles and programs fine now, but I can't see how to get the ADCValue into the TXREG. Or perhaps I'm not properly sampling AN0? The example I'm working from lights an LED dependant on the analogue voltage, but that uses a state machine to cycle through the LEDs. All that my program seems to do is light (flicker slightly) D1, D4 and D8, and seems to backspace on the terminal program. Turning the trimmer doesn't seem to have any effect. Is there a way to check where the problem is occurring - Sampling ADC, ADRESH to TXREG, TX? Also I wanted to have an LED flash slowly to show the program is running.

Code:
/*


*/

#include <htc.h>


__CONFIG(FCMDIS & IESODIS & BORDIS & UNPROTECT & UNPROTECT & MCLREN & PWRTDIS & WDTDIS & INTIO);

//Define Variables
int i,j;
int dlay = 63;
int ADCValue = 0;

void init_comms(void) {
	CMCON0 = 0x07;	//Comparators off. Digital I/O
	PORTA = 0x00;	//Initialise PortA, RA4 and RA5 
	PORTC = 0x30;	//Initialize PortC, RC5 and RC4
	TRISA = 0x00;	//Set RA4 and RA5 as outputs
	TRISC = 0x20;	//Set RC5 as an Input, RC4 to an Output

	//Desired Baud Rate = 9600, Fosc = 4MHz
	//Fosc/[16(n+1)] = Desired Baud Rate; where n = SPBRG
	SPBRG = 25;	//Set baud rate to 9600
	BRG16 = 0;	//8-bit Baud Rate Generator is used
	BRGH  = 1;	//High speed
	SYNC  = 0;	//Asynchronous mode
	TXEN  = 1;	//Transmit enabled
	SPEN  = 1;	//Serial port enabled
	CREN  = 1;	//Enables receiver
	RX9   = 0;	//Selects 8-bit reception
	TX9   = 0;	//Selects 8-bit transmission
	RCIE  = 0;	//Disables rx interrupts	
	TXIE  = 0;	//Disables tx interrupts
	PEIE  = 0;	//Disables interrupts for CPU

	//ADC Initialize
	ANSEL = 0x01;	//Set AN0 as ADC Input
	ADCON0 = 0x01;	//Turn on ADC
					//Bit 7 - Left Justified
					//Bit 6 - Use Vdd as ref.
					//Bit 4:2 - Channel 0
					//Bit 1 - Do Not Start
					//Bit 0 - Turn on ADC
	ADCON1 = 0x10;	//Select the clock Fosc/8

}

void putch(unsigned char byte)
{
	//output 1 byte
	while(!TXIF)	//set when register is empty
		continue;
	TXREG = byte;
}
//return

void ADCcon(void)
{
	ADCON0 = 0x02;
	GODONE = 1;
	if(!GODONE);
	{
	ADCValue = ADRESH;
	while(!TXIF)	//set when register is empty
		continue;
	TXREG = ADCValue;
	}
}

void main(void) 
{ 
	INTCON = 0;
	init_comms();
        while(1) 
        {
			for (i = 0; i < 255; i++);
			{
				for (j = 0; j < dlay; j++)
				{
				PORTA = 0x20;
				ADCcon();
	    		//ADCValue;
				//putch('U');
				
				}
			}
				PORTA = 0x00;
        }
}
 
Last edited:
Found the problem after looking through the code and datasheet AN0 is on RA0 pin and I was setting PORTA to all outputs effectly putting 0v on the AN0 input. But now I'm puzzling over the next problem - program waits for the button on RA3 to be pressed before running even though I don't think there is any code to perform that action. Does anyone know why its waiting for RA3?

Code:
/*


*/

#include <htc.h>


__CONFIG(FCMDIS & IESODIS & BORDIS & UNPROTECT & UNPROTECT & MCLREN & PWRTDIS & WDTDIS & INTIO);

//Define Variables
int i,j;
int dlay = 63;
int ADCValue = 0;
int ADCState = 0;

void init_comms(void) {
	CMCON0 = 0x07;	//Comparators off. Digital I/O
	PORTA = 0x00;	//Initialise PortA, RA4 and RA5 
	PORTC = 0x30;	//Initialize PortC, RC5 and RC4
	TRISA = 0x01;	//Set RA4 and RA5 as outputs
	TRISC = 0x20;	//Set RC5 as an Input, RC4 to an Output

	//Desired Baud Rate = 9600, Fosc = 4MHz
	//Fosc/[16(n+1)] = Desired Baud Rate; where n = SPBRG
	SPBRG = 25;	//Set baud rate to 9600
	BRG16 = 0;	//8-bit Baud Rate Generator is used
	BRGH  = 1;	//High speed
	SYNC  = 0;	//Asynchronous mode
	TXEN  = 1;	//Transmit enabled
	SPEN  = 1;	//Serial port enabled
	CREN  = 1;	//Enables receiver
	RX9   = 0;	//Selects 8-bit reception
	TX9   = 0;	//Selects 8-bit transmission
	RCIE  = 0;	//Disables rx interrupts	
	TXIE  = 0;	//Disables tx interrupts
	PEIE  = 0;	//Disables interrupts for CPU

	//ADC Initialize
	ANSEL = 0x01;	//Set AN0 as ADC Input
	ADCON0 = 0x01;	//Turn on ADC
					//Bit 7 - Left Justified
					//Bit 6 - Use Vdd as ref.
					//Bit 4:2 - Channel 0
					//Bit 1 - Do Not Start
					//Bit 0 - Turn on ADC
	ADCON1 = 0x10;	//Select the clock Fosc/8

}

void putch(unsigned char byte)
{
	//output 1 byte
	while(!TXIF)	//set when register is empty
		continue;
	TXREG = byte;
}
//return
/*
void ADCcon(void)
{
	ADCON0 = 0x02;
	GODONE = 1;
	if(!GODONE);
	{
	ADCValue = ADRESH;
	while(!TXIF)	//set when register is empty
		continue;
	TXREG = ADCValue;
	}

}*/



void main(void) 
{ 
	INTCON = 0;
	init_comms();
        while(1) 
        {
			for (i = 0; i < 255; i++)
			{
				for (j = 0; j < dlay; j++) {};
			}
				PORTA = 0x20;
					switch (ADCState)	//ADC State Machine
					{
					case 0:			//Finished, Start next sample
						GODONE = 1;
						ADCState++;
						break;
					case 1:			//Wait for ADC to complete
						if (!GODONE)
							ADCState++;
						break;
					case 2:			//Save sample value in "ADCValue"
						ADCValue = ADRESH;
						ADCState = 0;
						break;
								
					}
				putch(ADCValue);
				
				for (i = 0; i < 255; i++)
			{
				for (j = 0; j < dlay; j++) {};
			}
			
				PORTA = 0x00;
        }
}
 
Last edited:
RA3 is the MCLR pin. In your config word you have MCLR enabled (MCLREN) so the program should only run if RA3 is pulled high. I'm not sure how you have your buttons configured nor how you have RA3 hooked up when the button isn't pressed. I'm guessing it has to do with MCLR as you have RA3 set as an output, so there's nothing in your program "listening" for that pin. Are you using a particular development board or is this project on a breadboard?
 
The board is the PICKIT1 and the button is configured to pull RA3 down to gnd, aqnd is pulled up by a resistor when the button isn't pressed. Yes changing the config word to MCLRDIS made it run without any button pressing, thanks again. Its these small things I don't understand yet.

I've got it doing pretty much what I wanted it to - flash an led to show its running, measure a voltage on four analogue inputs and send them out on the serial in turn.

I've also got a simple LabView program to read the serial data.

Code:
/*


*/

#include <htc.h>


__CONFIG(FCMDIS & IESODIS & BORDIS & UNPROTECT & UNPROTECT & MCLRDIS & PWRTDIS & WDTDIS & INTIO);

//Define Variables
int i,j,k,m;
int dlay = 100;
int ADCValue = 0;
int ADCState = 0;
const char Channel[4] = {0x01, 0x01, 0x01, 0x01}; // AN0 only, repeated on all channels (test mode)
//const char Channel[4] = {0x01, 0x05, 0x09, 0x11}; // Channel select: AN0, AN1, AN2, AN4
const char Ident[4] = {0x31, 0x32, 0x33, 0x34};	// Identifiers are ASCII '1', '2', '3', '4' to test

void init_comms(void) {
	CMCON0 = 0x07;	//Comparators off. Digital I/O
	PORTA = 0x00;	//Clear PORTA 
	PORTC = 0x30;	//Clear PORTC
	TRISA = 0x1F;	//Set RA4 and RA5 as outputs
	TRISC = 0x20;	//Set RC5 as an Input, RC4 to an Output

	//Desired Baud Rate = 9600, Fosc = 4MHz
	//Fosc/[16(n+1)] = Desired Baud Rate; where n = SPBRG
	SPBRG = 25;	//Set baud rate to 9600
	BRG16 = 0;	//8-bit Baud Rate Generator is used
	BRGH  = 1;	//High speed
	SYNC  = 0;	//Asynchronous mode
	TXEN  = 1;	//Transmit enabled
	SPEN  = 1;	//Serial port enabled
	CREN  = 1;	//Enables receiver
	RX9   = 0;	//Selects 8-bit reception
	TX9   = 0;	//Selects 8-bit transmission
	RCIE  = 0;	//Disables rx interrupts	
	TXIE  = 0;	//Disables tx interrupts
	PEIE  = 0;	//Disables interrupts for CPU

	//ADC Initialize
	ANSEL = 0x17;	//Set AN0, AN1, AN2, AN4 as ADC Inputs
/*	ADCON0 = 0x01;	//Turn on ADC
					//Bit 7 - Left Justified
					//Bit 6 - Use Vdd as ref.
					//Bit 4:2 - Channel 0
					//Bit 1 - Do Not Start
					//Bit 0 - Turn on ADC
*/	ADCON1 = 0x10;	//Select the clock Fosc/8

}

void putch(unsigned char byte)
{
	//output 1 byte
	while(!TXIF)	//set when register is empty
		continue;
	TXREG = byte;
}

void main(void) 
{ 
	k = 0;
	INTCON = 0;
	init_comms();
        while(1) 
        {
			for (i = 0; i < dlay; i++)
			{
				for (j = 0; j < 160; j++) {};
			}
				PORTA = 0x20;
				
				
					ADCON0 = Channel[k];
					switch (ADCState)	//ADC State Machine
					{
					case 0:			//Finished, Start next sample
						GODONE = 1;
						ADCState++;
						break;
					case 1:			//Wait for ADC to complete
						if (!GODONE)
							ADCState++;
						break;
					case 2:			//Save sample value in "ADCValue"
						ADCValue = ADRESH;
						putch(Ident[k]); 	//Send Ident Byte (1,2,3,4)
				/*		for (i = 0; i < dlay; i++) //Delay to see whats happening
					{
						for (j = 0; j < 160; j++) {};
					}*/
						putch(ADCValue); //Send ADC Value
						ADCState = 0;
						k++;
						if (k == 4) k = 0;
						break;
								
					}
				//putch(ADCValue); //Send ADC result to Serial
				
						for (i = 0; i < dlay; i++)
					{
						for (j = 0; j < 160; j++) {};
					}
				
				PORTA = 0x00;
        }
}
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top