Simple C help PIC - Page 1
Forum section: electronics / beginners

author: Christopher
author_rank: Frequent Contributor
timestamp: March 29, 2013, 04:54:10 pm
content: Hi all, looking at function pointers in the PIC library im making. A hand would be great. If you can see a better way to do this than pointers let me know.In the user app they would:Code:void uart_rec_handler(unsigned char byte) {// play with byte here}...int main() {uart_setup(BAUD_RATE, &uart_rec_handler);}Code:/** Handles setup of uart communication with PIC micros.** File: uart.c* Author: chris** Created on 29 March 2013, 15:45*/#include <pic.h>#include <xc.h>typedef void (*callback_function)(void);callback_function uart_rec_handler;void uart_setup(unsigned long baud_rate, callback_function handler) {//..... removed register setupuart_rec_handler = &handler;}// ran on every interruptvoid uart_interrupt() {// usart recieve interruptif (PIE1bits.RCIE && PIR1bits.RCIF) {PIR1bits.RCIF = 0; // clear flag//callback_function(RCREG);uart_rec_handler();}}

author: kfitch42
author_rank: Frequent Contributor
timestamp: March 29, 2013, 05:12:33 pm
content: First, try to be consistent with your function signature. in the 'user app' code you have it taking an unsigned char, but in the library code you have it taking 0 params. I assume you would want it more like the user code.So change:typedef void (*callback_function)(void);totypedef void (*callback_function)(unsigned char byte);also that typedef (along with the declaration for uart_setup) belong in a header file that both the user code and library code would include.

author: Christopher
author_rank: Frequent Contributor
timestamp: March 29, 2013, 05:27:29 pm
content: Was doing that as a test. Still not working and i've done what you said...HeaderCode:/** File: uart.h* Author: chris** Created on 29 March 2013, 15:38*/#ifndef UART_H#defineUART_H#ifdef__cplusplusextern "C" {#endiftypedef void (*callback_function)(unsigned char byte);void uart_setup(unsigned long baud_rate, void (*handler) (unsigned char));void uart_transmit(unsigned char byte);// stringvoid uart_transmit();void uart_interrupt();#ifdef__cplusplus}#endif#endif/* UART_H */SourceCode:/** Handles setup of uart communication with PIC micros.** File: uart.c* Author: chris** Created on 29 March 2013, 15:45*/#include <pic.h>#include <xc.h>#include "uart.h"/*Follow the steps to receive data :- Load the SPBRG register for desired Baud Rate.-Set/Reset BRGH bit of TXSTA for high/low speed baud.-Enable Asynchronous mode by clearing SYNC bit of the TXSTA register.-Enable Serial Port by setting SPEN bit of RCSTA register.-Set the RCIE bit of the PIE1 register to enable Received Interrupt.-Set the GIE and PEIE bit of INTCON register to enable Peripheral Interrupts and General Interrupts.-Start to receive CREN bit of RCSTA register.-Get the received data from RCREG register at Interrupt routine check RCIF flag of PIR1 register to be sure if the interrupt was generated by USART Receiver.Follow the steps to transmit data :- Load the SPBRG register for desired Baud Rate.-Set/Reset BRGH bit of TXSTA for high/low speed baud.-Enable transmitter by setting TXEN bit of TXSTA register.-Load the data which will be transmitted, to TXREG register to start transmission.*/#ifndef _XTAL_FREQ#define _XTAL_FREQ 9600#endifcallback_function uart_rec_handler;void uart_setup(unsigned long baud_rate, callback_function handler) {// calculate baud rate registerSPBRG = ( _XTAL_FREQ / (baud_rate / 64) ) - 1;//SPBRG = 0x33; //9600 baudTXSTAbits.BRGH = 0; // low speed. What baud rate means high speed?!// recieveTXSTAbits.SYNC = 0; // enable async modeRCSTAbits.SPEN = 1; // serial enablePIE1bits.RCIE = 1; //enable uart recieve interruptRCSTAbits.CREN = 1; //enable continuous receive// sendTXSTAbits.TXEN = 1; // transmit enablePIE1bits.TXIE = 1; // transmit interrupt enable// global interrupts. Should i keep this here or assume user will ei()???INTCONbits.PEIE = 1; // peripheral interrupt enableei();uart_rec_handler = &handler;}void uart_transmit(unsigned char byte) {while(!PIR1bits.TXIF) // wait till previous data has been sentcontinue;TXREG = byte;}// ran on every interruptvoid uart_interrupt() {// usart recieve interruptif (PIE1bits.RCIE && PIR1bits.RCIF) {PIR1bits.RCIF = 0; // clear flag//callback_function(RCREG);(*uart_rec_handler)(RCREG);}// usart transmit interruptif (TXSTAbits.TXEN && PIE1bits.TXIE) {PIE1bits.TXIE = 0; // clear flag//TXREG = 0x00;}}Errors:uart.c:60: warning: illegal conversion between pointer typesuart.c:37: error: conflicting declarations for variable "_uart_rec_handler" (main.c:12)

author: kfitch42
author_rank: Frequent Contributor
timestamp: March 29, 2013, 06:07:54 pm
content: uart.c line 60: Drop the '&'. the typedef already include the fact that it is a pointer. So by adding the ampersand you are creating a pointer-to-a-pointer-to-a-function on the right hand side of the assignment. The left hand side is just a pointer-to-a-function. The difference in the number of levels of indirection (i.e. number 'pointer-to's) is what the compiler is complaining about.uart.c line 37: Not sure what it is complaining about, but it also references main.c line 12, which I don't think you showed us. smells like you have two different things with the name uart_rec_handler. perhaps a function in main.c?!? Did you #include "uart.c" in main.c ? main.c should #include "uart.h". You have redacted enough of the output that I am note sure if this error is compile time or link time.As a matter of good practice you should declare anything that is only used in one file as static.e.g. in uart.c the linecallback_function uart_rec_handler;should probably change tostatic callback_function uart_rec_handler;this tells the compiller that uart_rec_handler can ONLY be used in uart.c, which avoids accidental link time name collisions if e.g. a user of the library happens to name something uart_rec_handler. Also, this can help the compiler make better optimization decisions.

author: madshaman
author_rank: Frequent Contributor
timestamp: March 29, 2013, 06:14:02 pm
content: Post your main.c please

author: Christopher
author_rank: Frequent Contributor
timestamp: March 29, 2013, 06:17:33 pm
content: Very nice, all fixed! Thanks!Looking at the error again and it was a very stupid mistake, I called the function in my main.c uart_rec_handler & obviously the function and the variable cannot have the same name.The static keyword helped a lot. Thanks a lot!!