I do not know if I am initializing ADC correctly for PIC24F - pic

I am using a Microchip Pic24f board to receive 3 analog inputs from a accelerometer.
I am getting a signal for AN0 but for AN1 and AN2 there is a signal but the values are not right.
Here is the code where I initialize ADC.
void InitADC(int amask) {
AD1PCFG = 0xFFF8; // select AN0, AN1, AN2 as analog input
AD1CON1 = 0x00E0; // auto convert # end of sampling, Integer Data in.
AD1CON2 = 0x0000; // use MUXA, AVss and AVdd used as Vref
AD1CON3 = 0x1F01; // Tad = 2xTcy = 125ns. 31*Tad for conversion time.
AD1CSSL = 0; // no scanning required
AD1CHS=0;
AD1CHS=1;
AD1CHS=2;
AD1CON1bits.ADON = 1; // Turn on the ADC
} // InitADC
In the main():
TRISBbits.TRISB0 = 1;
TRISBbits.TRISB1 = 1;
TRISBbits.TRISB2 = 1;
I then read AD1PCFG = 0xFFFE; for each analog input in a different function.
The results of the inputs are read in by in that same function
return ADC1BUF0;
I am not sure if for the PIC24f if I need to use ADC1BUFx for each ANx analog input or if I can read the signals through just ADC1BUF0.
Also I do not know if I need to scan and for AD1CON2 the configuration needs to be different because of the multiple analog inputs being used.
I am fairly new to PIC24f and have searched everywhere for help and everything that I was able to try got me to get the signals to be read on the LCD but AN1 and AN2 data is not what it is supposed to be.
If anyone could help me that it would be appreciated.

This is an example that show how I implemented what is found in the Microchip family reference manual describing the type of ADC you may be using:
/*
* File: main.c
* Author: dan1138
* Target: PIC24FJ64GA002
* IDE: MPLABX v5.45
* Compiler: XC16 v1.61
*
* Description:
*
* Initialize the ADC to convert voltage levels present on AN0, AN1 and AN5
*
* Map UART1 with TXD on RB0 and RXD on RB1.
* Map UART2 with TXD on RB8 and RXD on RB8.
*
* Initialize UART2 at 9600 baud and hook to printf.
*
* Created on March 11, 2021, 1:46 PM
*
* See: https://stackoverflow.com/questions/66552251/i-do-not-know-if-i-am-initializing-adc-correctly-for-pic24f
*
* PIC24FJ64GA002
* +-----------------:_:-----------------+
* ICD_VPP -> : 1 MCLR VDD 28 : <- 3v3
* <> : 2 RA0/RP26/AN0 VSS 27 : <- GND
* <> : 3 RA1/RP27/AN1 AN9 /RP15/RB15 26 : <> LED4
* ICD_PGD <> : 4 RB0/PGD1/AN2 AN10/RP14/RB14 25 : <> LED5
* ICD_PGC <> : 5 RB1/PGC1/AN3 AN11/RP13/RB13 24 : <> LED6
* <> : 6 RB2/RP2/AN4 AN12/RP12/RB12 23 : <> LED7
* POT <> : 7 RB3/RP3/AN5 RP11/RB11 22 : <>
* GND -> : 8 VSS RP10/RB10 21 : <>
* 7.3728MHz <> : 9 RA2/OSCI VCAP 20 : <- 10uF
* 7.3728MHz <> : 10 RA3/OSCO VSS 19 : <- GND
* <> : 11 RB4/SOSC RP9 /RB9 18 : <> RXD
* <> : 12 RA4/SOSC RP8 /RB8 17 : <> TXD
* 3v3 -> : 13 VDD INT0/ RP7 /RB7 16 : <>
* SW1 <> : 14 RB5/RP5 RP6 /RB6 15 : <>
* +-------------------------------------+
* DIP-28
*
*/
// CONFIG2
#pragma config POSCMOD = NONE // Primary Oscillator Select (Primary oscillator disabled)
#pragma config I2C1SEL = PRI // I2C1 Pin Location Select (Use default SCL1/SDA1 pins)
#pragma config IOL1WAY = OFF // IOLOCK Protection (IOLOCK may be changed via unlocking seq)
#pragma config OSCIOFNC = ON // Primary Oscillator Output Function (OSC2/CLKO/RC15 functions as port I/O (RC15))
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor (Clock switching and Fail-Safe Clock Monitor are disabled)
#pragma config FNOSC = FRCPLL // Oscillator Select (Fast RC Oscillator with PLL module (FRCPLL))
#pragma config SOSCSEL = SOSC // Sec Oscillator Select (Default Secondary Oscillator (SOSC))
#pragma config WUTSEL = LEG // Wake-up timer Select (Legacy Wake-up Timer)
#pragma config IESO = ON // Internal External Switch Over Mode (IESO mode (Two-Speed Start-up) enabled)
// CONFIG1
#pragma config WDTPS = PS32768 // Watchdog Timer Postscaler (1:32,768)
#pragma config FWPSA = PR128 // WDT Prescaler (Prescaler ratio of 1:128)
#pragma config WINDIS = ON // Watchdog Timer Window (Standard Watchdog Timer enabled,(Windowed-mode is disabled))
#pragma config FWDTEN = OFF // Watchdog Timer Enable (Watchdog Timer is disabled)
#pragma config ICS = PGx1 // Comm Channel Select (Emulator EMUC1/EMUD1 pins are shared with PGC1/PGD1)
#pragma config GWRP = OFF // General Code Segment Write Protect (Writes to program memory are allowed)
#pragma config GCP = OFF // General Code Segment Code Protect (Code protection is disabled)
#pragma config JTAGEN = OFF // JTAG Port Enable (JTAG port is disabled)
#define FCY (16000000ul) // This define allows the delay macros to work
#include "xc.h"
#include <libpic30.h>
#include <stdio.h>
/* define map input pin numbers */
enum
{
RPI0 = 0, /* pin RB00 */ /* PGC1 */
RPI1, /* pin RB01 */ /* PGD1 */
RPI2, /* pin RB02 */
RPI3, /* pin RB03 */
RPI4, /* pin RB04 */
RPI5, /* pin RB05 */
RPI6, /* pin RB06 */
RPI7, /* pin RB07 */
RPI8, /* pin RB08 */
RPI9, /* pin RB09 */
RPI10, /* pin RB10 */
RPI11, /* pin RB11 */
RPI12, /* pin RB12 */
RPI13, /* pin RB13 */
RPI14, /* pin RB14 */
RPI15, /* pin RB15 */
RPI_NONE = 0x1f
};
/* define map output function numbers */
enum
{
RPO_NONE = 0,
RPO_C1OUT,
RPO_C2OUT,
RPO_U1TX,
RPO_U1RTS,
RPO_U2TX,
RPO_U2RTS,
RPO_SDO1,
RPO_SCK1OUT,
RPO_SS1OUT,
RPO_SDO2,
RPO_SCK2OUT,
RPO_SS2OUT,
RPO_OC1=18,
RPO_OC2,
RPO_OC3,
RPO_OC4,
RPO_OC5,
};
/* Initialize this PIC */
void
PIC_Init(
void
)
{
/*
** Disable all interrupt sources
*/
__builtin_disi(0x3FFF); /* disable interrupts for 16383 cycles */
IEC0 = 0;
IEC1 = 0;
IEC2 = 0;
IEC3 = 0;
IEC4 = 0;
__builtin_disi(0x0000); /* enable interrupts */
CLKDIV = 0x0000; /* set for default clock operations */
AD1PCFG = 0xffff; /* Set for digital I/O */
#ifdef AD1PCFGH
AD1PCFGH = 0xffff;
#endif
CMCON = 0x0000;
_NSTDIS = 1; /* disable interrupt nesting */
TRISA = 0xFFFF;
TRISB = 0xFFFF;
/* Unlock Registers */
__builtin_write_OSCCONL(OSCCON & ~_OSCCON_IOLOCK_MASK);
/* map inputs */
_INT1R = RPI_NONE; /* External Interrupt 1 */
_INT2R = RPI_NONE; /* External Interrupt 2 */
_T2CKR = RPI_NONE; /* Timer2 External Clock */
_T3CKR = RPI_NONE; /* Timer3 External Clock */
_T4CKR = RPI_NONE; /* Timer4 External Clock */
_T5CKR = RPI_NONE; /* Timer5 External Clock */
_IC1R = RPI_NONE; /* Input Capture 1 */
_IC2R = RPI_NONE; /* Input Capture 2 */
_IC3R = RPI_NONE; /* Input Capture 3 */
_IC4R = RPI_NONE; /* Input Capture 4 */
_IC5R = RPI_NONE; /* Input Capture 5 */
_OCFAR = RPI_NONE; /* Output Compare Fault A */
_OCFBR = RPI_NONE; /* Output Compare Fault B */
_U1RXR = RPI1; /* UART1 Receive */
_U1CTSR = RPI_NONE; /* UART1 Clear To Send */
_U2RXR = RPI9; /* UART2 Receive */
_U2CTSR = RPI_NONE; /* UART2 Clear To Send */
_SDI1R = RPI_NONE; /* SPI1 Data Input */
_SCK1R = RPI_NONE; /* SPI1 Clock Input */
_SS1R = RPI_NONE; /* SPI1 Slave Select Input */
_SDI2R = RPI_NONE; /* SPI2 Data Input */
_SCK2R = RPI_NONE; /* SPI2 Clock Input */
_SS2R = RPI_NONE; /* SPI2 Slave Select Input */
/* map outputs */
_RP0R = RPO_U1TX; /* U1 TXD */ /* pin RB00 */ /* PGC1 */
_RP1R = RPO_NONE; /* U1 RXD */ /* pin RB01 */ /* PGD1 */
_RP2R = RPO_NONE; /* pin RB02 */
_RP3R = RPO_NONE; /* pin RB03 */
_RP4R = RPO_NONE; /* pin RB04 */
_RP5R = RPO_NONE; /* pin RB05 */
_RP6R = RPO_NONE; /* pin RB06 */
_RP7R = RPO_NONE; /* pin RB07 */
_RP8R = RPO_U2TX; /* U2 TXD */ /* pin RB08 */
_RP9R = RPO_NONE; /* U2 RXD */ /* pin RB09 */
_RP10R = RPO_NONE; /* pin RB10 */
_RP11R = RPO_NONE; /* pin RB11 */
_RP12R = RPO_NONE; /* pin RB12 */
_RP13R = RPO_NONE; /* pin RB13 */
_RP14R = RPO_NONE; /* pin RB14 */
_RP15R = RPO_NONE; /* pin RB15 */
/* Lock Registers */
__builtin_write_OSCCONL(OSCCON | _OSCCON_IOLOCK_MASK);
}
/*
* Initialize the ADC
*/
static const uint8_t Selector[] = {0x00,0x01,0x05};
void ADC_Init(void)
{
AD1PCFGbits.PCFG0 = 0; /* AN0/RA0 */
AD1PCFGbits.PCFG1 = 0; /* AN1/RA1 */
AD1PCFGbits.PCFG5 = 0; /* AN5/RB3 */
TRISAbits.TRISA0 = 1;
TRISAbits.TRISA1 = 1;
TRISBbits.TRISB3 = 1;
AD1CON1 = 0x0000; // SAMP bit = 0 ends sampling and starts converting
AD1CHS = 0x0000; // default to channel 0
AD1CSSL = 0;
AD1CON3 = 0x0102; // Manual Sample, TAD = 3 TCY, Auto-Sample Time 1 TAD
AD1CON2 = 0;
AD1CON1bits.ADON = 1; // turn ADC ON
}
/*
* ADC Read channel
*/
uint16_t ADC_ReadChannel(uint16_t Index)
{
if(Index < sizeof(Selector))
{
AD1CHSbits.CH0SA = Selector[Index];
}
AD1CON1bits.SAMP = 1; // start sampling...
__delay_us(5); // Ensure the correct sampling time has elapsed before starting conversion.
AD1CON1bits.SAMP = 0; // start converting
for(;;)
{
if(AD1CON1bits.DONE) break; // conversion done?
}
return ADC1BUF0; // yes then get ADC value
}
/*
* Initialize UART2
*/
#define U2_BAUD 9600L
#define U2_BRGH_VALUE 0
#if U2_BRGH_VALUE
#define U2_BRGH_SCALE 4L
#else
#define U2_BRGH_SCALE 16L
#endif
#define U2_BRGREG (FCY/(U2_BRGH_SCALE * U2_BAUD)-1L)
#if U2_BRGREG > 65535
#error Cannot set up UART2 for the FCY and BAUDRATE. Correct values in init.h and uart.h files.
#endif
/*
** Check if baud error greater than 2.5 percent
*/
#define REAL_BAUDRATE ( FCY / ( U2_BRGH_SCALE * ( U2_BRGREG + 1L) ) )
#if (REAL_BAUDRATE > (U2_BAUD + (U2_BAUD * 25L) / 1000L)) || (REAL_BAUDRATE < (U2_BAUD - (U2_BAUD * 25L) / 1000L))
#error UART baudrate error greater than 2.5 percent for the FCY and U2_BAUD. Correct values in uart.c file.
#endif
#undef REAL_BAUDRATE
void UART2_Init(void)
{
_U2TXIE = 0;
_U2RXIE = 0;
_U2ERIE = 0;
_U2RXIP = 0b100;
_U2TXIP = 0b100;
_U2ERIP = 0b100;
U2MODE = 0;
U2STA = 0;
U2BRG = U2_BRGREG;
U2MODEbits.BRGH = U2_BRGH_VALUE;
U2MODEbits.UARTEN = 1;
U2STAbits.UTXEN = 1;
}
void UART2_Write(uint8_t txData)
{
while(U2STAbits.TRMT != 1);
U2TXREG = txData; // Write the data byte to the USART.
}
/*
* hook for printf
*/
int __attribute__((__section__(".libc.write"))) write(int handle, void *buffer, unsigned int len)
{
unsigned int i;
for (i = len; i; --i)
{
UART2_Write(*(char*)buffer++);
}
return(len);
}
/*
* Main Application
*/
int main(void)
{
uint16_t ADC_results[sizeof(Selector)];
uint16_t ADC_value;
uint16_t NewResults;
uint16_t Index;
PIC_Init();
ADC_Init();
UART2_Init();
printf("\r\nPIC24FJ64GA002 start, built on %s at %s\r\n", __DATE__, __TIME__);
/*
* Application loop
*/
NewResults = 1;
for(;;)
{
for(Index = 0; Index < sizeof(Selector); Index++)
{
ADC_value = ADC_ReadChannel(Index);
if (ADC_value != ADC_results[Index])
{
NewResults |= 1;
}
ADC_results[Index] = ADC_value;
}
if(NewResults)
{
NewResults = 0;
printf("Values");
for(Index = 0; Index < (sizeof(ADC_results)/sizeof(*ADC_results) ); Index++)
{
printf(" AN%1u = %5u", Selector[Index], ADC_results[Index]);
}
printf("\r\n");
}
}
return 0;
}
You do not provide enough information in your post to know which one of the 55 controllers you may actually be using.
I used the PIC24FJ64GA002 controller that I can find right now that has the ADC hardware you could be using.

Related

PLL turning on when debugging on STM32F767 Nucleo

I have been scratching my head for the past 2 days trying to figure out what is wrong with my very simple UART program on System Workbench for STM32 from STMicroelectronics. For some reason when I set:
USART3->BRR = (16000000/9600); //Sets the baud rate to 9600 with a clock of 16MHz
The output on the serial line is rubbish, however when I press the reset button on the board and let it run, I see
Hello World
As expected. Doing some digging I found out that the source for the system clock is the PLL output (RCC_CFGR register), red arrow on the imagem bellow:
RCC_CFGR
The bits correspondent to the red arrows tells me that the PLL is ON. Analyzing the RCC_PLLCFGR register and inputing the PLLM, PLLN and PLLP parameters togheter with the correspondents prescallers (AHB and APB1) into the CubeMX I arrived at a APB1 bus clock of 48MHz. So I did:
USART3->BRR = (48000000/9600); //Sets the baud rate to 9600 with a clock of 48MHz
And voilà doing step by step on the debugger I can see "HELLO WORLD" so the bus clock is 48MHz.
BUT, and I press the reset button and leave it running now the output is non-sense. Something on the debugging process is turning on the PLL and using it as the SYSCLK source.
I copied and pasted the code into Keil uVision and there was no problem, debugging and running, so the problem isn't the code itself. I took a look at the startup_stm32.s, core_cm7.h and debug files from SW4STM32 and couldn't find any hint as to why this is happening. Looking in the reference manual Reference Manual on page 170 the reset value of RCC_CFGR is 0x0000.0000 so the PLL is TURNED OFF after reset, so something in the debugging is actively setting the PLL ON.
I am using Tera Term to look at the ST-LINK serial port and Digital Discovery from Digilent to confirm what is going on the bus, and both give me even data.
Any ideas?
Full code:
#include "stm32f767xx.h"
#include "time.h"
/*
* Function declarations
*/
void uS_Delay(int Time);
void mS_Delay(int Time);
void S_Delay(int Time);
void GPIOAa_Init(void);
void Config_TIM5(void);
void TIM5_IRQHandler(void);
void Enable_TIM5Interrupt(void);
void UART_Config(void);
void UART_Send(int character);
int Delay_End = 0;
int main(void)
{
GPIOD_Init();
Config_TIM5();
Enable_TIM5Interrupt();
UART_Config();
int butao = 0;
while(1)
{
UART_Send('H');
mS_Delay(10);
UART_Send('E');
mS_Delay(10);
UART_Send('L');
mS_Delay(10);
UART_Send('L');
mS_Delay(10);
UART_Send('O');
mS_Delay(10);
UART_Send(' ');
mS_Delay(10);
UART_Send('W');
mS_Delay(10);
UART_Send('O');
mS_Delay(10);
UART_Send('R');
mS_Delay(10);
UART_Send('L');
mS_Delay(10);
UART_Send('D');
mS_Delay(10);
}
}
/*
* Functions
*/
void uS_Delay(int Time){
uint32_t Delay = (uint32_t) (unsigned long) (Time*16);
/* The APB bus cycle period is by default 62.5 nS, defined by the
* default bus frequency of 16 MHz. The number of steps to produce
* a 1 uS clock is:
*
* Nº Steps = 1uS/62.5nS
* Nº Steps = 16
*
* So for a delay of "Time" microseconds the number of steps is:
*
* Delay = Time*16
*/
TIM5->ARR = Delay;
/* TIM-ARR value will be the counter boundary to roll over.
* The default bus frequency is 16MHz.
*/
TIM5->CR1 |= 0x09;
/* TIM5->CR1 is the main basic timer controller, in this situation
* the bits 0 and 3 are been set. Those bits enables the counting
* itself and the one-shot-mode, respectively. One-shot-mode makes
* it so when an update event occurs (overflow, underflow, etc) the
* counter stops counting, in other words the bit 0 of TIM%->CR1
* is cleared.
*/
Delay_End = 0;
while(Delay_End == 0);
Delay_End = 0;
/* Delay_End is a flag telling the uS_Delay() function that the
* specified delay hasn't finished (Delay_End = 0), so keeps the
* PC register stuck on (while(Delay_End == 0)). When the counter
* rolls over it generates an interrupt. The handler (TIM5_IRQHandler)
* sets this flag and now the program can get out of the while loop
* the flag is once again cleared (Delay_End = 0) and the program
* resumes.
*/
}
void mS_Delay(int Time){
uint32_t Delay = (uint32_t) (unsigned long) (Time*16000);
/* The APB bus cycle period is by default 62.5 nS, defined by the
* default bus frequency of 16 MHz. The number of steps to produce
* a 1 mS clock is:
*
* Nº Steps = 1uS/62.5nS
* Nº Steps = 16.000
*
* So for a delay of "Time" microseconds the number of steps is:
*
* Delay = Time*16.000
*/
TIM5->ARR = Delay;
/* TIM-ARR value will be the counter boundary to roll over.
* The default bus frequency is 16MHz.
*/
TIM5->CR1 |= 0x09;
/* TIM5->CR1 is the main basic timer controller, is this situation
* the bits 0 and 3 are been set. Those bits enables the counting
* itself and the one-shot-mode, respectively. One-shot-mode makes
* it so when an update event occurs (overflow, underflow, etc) the
* counter stops counting, in other words the bit 0 of TIM%->CR1
* is cleared.
*/
Delay_End = 0;
while(Delay_End == 0);
Delay_End = 0;
/* Delay_End is a flag telling the uS_Delay() function that the
* specified delay hasn't finished (Delay_End = 0), so keeps the
* PC register stuck on (while(Delay_End == 0)). When the counter
* rolls over it generates an interrupt. The handler (TIM5_IRQHandler)
* sets this flag and now the program can get out of the while loop
* the flag is once again cleared (Delay_End = 0) and the program
* resumes.
*/
}
void S_Delay(int Time){
uint32_t Delay = (uint32_t) (unsigned long) (Time*16000000);
/* The APB bus cycle period is by default 62.5 nS, defined by the
* default bus frequency of 16 MHz. The number of steps to produce
* a 1 S clock is:
*
* Nº Steps = 1S/62.5nS
* Nº Steps = 16.000.000
*
* So for a delay of "Time" seconds the number of steps is:
*
* Delay = Time*16.000.000
*/
TIM5->ARR = Delay;
/* TIM-ARR value will be the counter boundary to roll over.
* The default bus frequency is 16MHz.
*/
TIM5->CR1 |= 0x09;
/* TIM5->CR1 is the main basic timer controller, is this situation
* the bits 0 and 3 are been set. Those bits enables the counting
* itself and the one-shot-mode, respectively. One-shot-mode makes
* it so when an update event occurs (overflow, underflow, etc) the
* counter stops counting, in other words the bit 0 of TIM%->CR1
* is cleared.
*/
Delay_End = 0;
while(Delay_End == 0);
Delay_End = 0;
/* Delay_End is a flag telling the uS_Delay() function that the
* specified delay hasn't finished (Delay_End = 0), so keeps the
* PC register stuck on (while(Delay_End == 0)). When the counter
* rolls over it generates an interrupt. The handler (TIM5_IRQHandler)
* sets this flag and now the program can get out of the while loop
* the flag is once again cleared (Delay_End = 0) and the program
* resumes.
*/
}
void GPIOD_Init(void){
int a;
RCC->AHB1ENR |= 0x08; //Enables clock for port D
a = RCC->AHB1ENR; //Small delay
GPIOD->MODER |= 0x00020000;
/*
* Sets output mode for alternate mode for pin PD8
*/
GPIOD->AFR[1] |= 0x00000007;
/*
* Alternate function 7 selected for pin PD8
*/
}
void Config_TIM5(void){
int a;
RCC->APB1ENR |= 0x08; //Enables clock for TIM5
a = RCC->APB1ENR; //Small delay
TIM5->DIER |= 0X01; //Enables update interrupt
}
void TIM5_IRQHandler(void){
Delay_End = 1; //The specified delay time has ended
TIM5->SR &= ~(0x01); //Clears the update event flag
}
void Enable_TIM5Interrupt(void){
NVIC->ISER[1] = 0x40000; //Enables interrupt event from TIM5 peripheral
NVIC->IP[50] = 0x00; //Sets the priority for the TIM5 interrupt
}
void UART_Config(void){
int a;
RCC->APB1ENR |= 0x00040000; //Enable clock for UART4
a = RCC->APB1ENR; //Small delay
USART3->CR1 |= 0x08; //Enable the transmitter
USART3->BRR = (48000000/9600); //Sets the baud rate to 9600
USART3->CR1 |= 0x01; //Enable the USART4
}
void UART_Send(int character){
USART3->TDR = (character);
}
Edit1: I got confused with RCC_CR and RCC_CFGR but the problem is the same.
Edit2: I noticed that the prescalers for APB1 and APB2 buses were also changed.
Edit3: Workaround when you start the debugging session press the icon(Reset the chip and restart debug session), this button will restart the debug session with a reset. This way the contents of the registers are as expected. I am still on the look for a mre permanent solution.

PIC - timer0 and interrupt to count and blink LED

I'm using PIC10F322 and timer0 with interrupt, trying to blink an LED, on for 1s and then off for another 1s. I had tried coded the timer called for interrupt, and it work good. But the counting for time isn't correct. The counting was On for about 2s and then Off for another 2s, which is isn't correct. I wonder is there something wrong with the calculation? The chip is 16MHZ, timer0 is 8 bits and set prescaler to 256. My attempt is to trigger interrupt every 1ms, then do a 999 loop count to hit 1 second.
My calculation is:
256 - [(Delay * Fosc) / (prescaler*4)] = 256 - [(1ms * 16000000)/(256*4)] = 240
#define _XTAL_FREQ 16000000
#include <xc.h>
#pragma config FOSC = INTOSC // Oscillator Selection bits (INTOSC oscillator: CLKIN function disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select bit (MCLR pin function is MCLR)
#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
#pragma config LPBOR = ON // Brown-out Reset Selection bits (BOR disabled)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
int z = 0,count=0;
void main(void) {
ANSELA = 0x00;
TRISA = 0b0100;
TRISAbits.TRISA2 = 1;
LATAbits.LATA0 = 0;
INTCONbits.GIE=1; /* Enable Global Interrupt*/
INTCONbits.PEIE = 1; /* Enable peripheral Interrupt */
OPTION_REGbits.T0CS = 0;
OPTION_REGbits.PSA = 0;
OPTION_REGbits.PS0 = 1; /* set prescaler to 256 */
OPTION_REGbits.PS1 = 1;
OPTION_REGbits.PS2 = 1;
OPTION_REGbits.INTEDG = 0;
TMR0 = 240;
INTCONbits.TMR0IF = 0;
INTCONbits.TMR0IE = 1;
while(1){
}
return;
}
void __interrupt(high_priority) tcInt(void)
{
if (TMR0IE && TMR0IF)
{
TMR0 = 240;
TMR0IF = 0;
if (count == 999)
{
z = 0;
LATAbits.LATA0 = ~LATAbits.LATA0;
count =0;
}
count++;
}
return;
}
You timer calculation is fine but I guess your microcontroller is running at 8 MHz which is the default value after reset if you are working with the internal oscillator (#pragma config FOSC = INTOSC). If you like 16 MHz, you had to do the selection in the OSCCON register.
OSCCON = 0b01110000;

program - UART communication for pic18f65k40

I'm searching UART code for pic18f65k40, but i haven't found yet.
Could anyone please provide a sample code to transmit a single character using pic18f65k40 uart.
This is the driver from my neolight theatre lighting controller. It is for a PIC18F14K22, but should be close enough to give you a start. This board also bit bangs the extremely fast protocol for the World Semi LEDs, hence the comment about timing.
/* Neolight board optional UART support. The UART is used as an
alternative to contact closures to trigger effects, and can be used
to download completely arbitrary patterns to the LEDS.
NOTE that during a write to the LEDs there are NO cycles left over
to operate the UART, so it does not work during updates. The
protocol reflects this.
*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "neolight.h"
/* Baud rate calculation */
#define brgh 1 /* Use high rate mode */
#if brgh
#define divisor 4
#else
#define divisor 64
#endif
/* Macros to compute baud rate setup at compile time */
#define spbrg ( ( (long) Fosc ) / ( (long) divisor * (long) ( baud_rate ) ) - 1 )
#define spbrgl ( spbrg & 0xFF )
#define spbrgh ( ( spbrg >> 8 ) & 0xFF )
/* Turn on the UART and set baud rate */
void uart_setup ()
{
RCSTAbits . SPEN = 1 ;
BAUDCONbits . BRG16 = 1 ;
TXSTAbits . TXEN = 1 ;
TXSTAbits . BRGH = brgh ;
RCSTAbits . CREN = 1 ;
SPBRG = spbrgl ;
SPBRGH = spbrgh ;
}
/* Send data to UART */
void uart_send ( unsigned char * buffer, int count )
{
int n ;
for ( n = 0; n < count; n++ )
{
while ( !TXSTAbits . TRMT ) ;
TXREG = buffer [ n ] ;
}
}
/* Receive from UART, return -1 if no char */
int uart_receive ()
{
if ( RCSTAbits . OERR )
{
RCSTAbits . CREN = 0 ;
RCSTAbits . CREN = 1 ;
}
if ( PIR1bits . RCIF )
return RCREG ;
else
return -1 ;
}
void Setup_UART(void)
{
TX1STA = 0b00100100;
RC1STA = 0b00010000;
BAUDCON1 = 0b00001000;
SP1BRGL = xxx; //Baudrate value, look at datasheet
SP1BRGH = xxx;
RCSTA1bits.SPEN = 1;
}
void Send_Byte(uint8_t Data)
{
while (!PIR3bits.TXIF);
TX1REG = Data;
}
This example works for the PIC1827k40. Please have a look at the datasheet for your controller.

MPLAB X IDE ADC code not working

i am a beginner to microcontroller and I just got into ADC but whenever I try to do a conversion it never works, I am trying to display the result on an LCD but the problem is not the LCD's because I tried its code alone and it worked so the problem is definitely the ADC's registers, here is the full code::
main.c:
#include "config.h"
int result;
void main(){
TRISAbits.TRISA0 = 1; //Set Port A for input
ADCON0 = 0b01000000; //Configuring ADCON0 register
ADCON1 = 0b10000000; //Configuring ADCON1 register
ADCON0bits.ADON = 1; //Turn on ADON bit in ADCON0 register to turn on ADC module
__delay_us(50); //Delay for the capacitor to be charged
ADCON0bits.GO_DONE = 1;
while(ADCON0bits.GO_DONE == 1);
result = ADRESH && ADRESL;
initLCD();
write_character(result);
while(1);
}
config.h:
#include <xc.h>
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
// CONFIG
#pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = ON // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#define _XTAL_FREQ 4000000
void send_command(int command);
void write_character(int character);
void enable_blink(void);
void moveto(char b6, char b5, char b4, char b3, char b2, char b1, char b0);
void initLCD(void);
void send_command(int command){
PORTCbits.RC0 = 0;
PORTB = command;
enable_blink();
}
void write_character(int character){
PORTCbits.RC0 = 1;
PORTB = character;
enable_blink();
}
void enable_blink(){
PORTCbits.RC1 = 1;
__delay_ms(10);
PORTCbits.RC1 = 0;
__delay_ms(10);
}
void moveto(char b6, char b5, char b4, char b3, char b2, char b1, char b0){
PORTCbits.RC0 = 0;
PORTBbits.RB7 = 1;
PORTBbits.RB6 = b6;
PORTBbits.RB5 = b5;
PORTBbits.RB4 = b4;
PORTBbits.RB3 = b3;
PORTBbits.RB2 = b2;
PORTBbits.RB1 = b1;
PORTBbits.RB0 = b0;
enable_blink();
}
void initLCD(){
TRISB = 0;
TRISC = 0;
send_command(0x38);
__delay_us(40);
send_command(0x01);
__delay_ms(1.75);
send_command(0x0C);
__delay_us(40);
}
You may have a problem with your result line. Try the following:
result = ( ( ADRESH << 8 ) | ( ADRESL ) )
The double & operator ( && ) is the logical AND. AND will return true ( 1 ) as long as ADRESH and ADRESL are both greater than 1. You want the bitwise OR ( | ) operator to combine two bytes into one int, with the ADRESH as the most-significant-byte and the ADRESL as the least-significant-byte.
Hopefully this works!

Logical error in comparing character recieved in USART

I Want to compare the character recieved via RX pin of ATMEGA 8. WHy doesn't the comparison work?
int main()
{
DDRB = 0XFF;
UCSRB = (1<<RXEN);
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
UBRRL = 0X33;
char r;
while (1)
{
while(!(UCSRA&(1<<RXC)));
r = UDR;
if(r=='r') PORTB = 0XFF;
}
return 0;
}
Sample code for easy setting baud_rate
#define F_CPU 8000000UL // Chip CPU frequency here, prevents default 1MHz
#define USART_BAUDRATE 19200UL // Baud_rate here, baudrates: 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
#include <avr/io.h>
int main(void) {
DDRB = 0XFF;
UBRRL = BAUD_PRESCALE; // baud to low byte of the UBRR register
UBRRH = (BAUD_PRESCALE >> 8); // baud to high byte of the UBRR register
UCSRB = (1<<RXEN);
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
char r;
while(1) {
//TODO:: Please write your application code
while(!(UCSRA&(1<<RXC)));
r = UDR;
if(r=='r') PORTB = 0XFF;
}
return 0;
}

Resources