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.
Related
I am new to arduino and I am trying to make a program that calculates the percentage of charge remaining in a battery, using the coulomb countig method (below a picture with the formula). Is it possible to perform this type of calculation from an arduino?
1.) The Model
Assuming CBat is the capacity of a battery and constant (physicist prefer letter Q for electrical charge; CBat may decrease with aging, "State of Health")
By Definition:
SOC(t) = Q(t)/CBat
Differential Equation:
dQ/dt = I(t)
Approximation: "dt=1"
Q(t)-Q(t-1) ~= I(t)
Or
SOC(t) ~= SOC(t-1) + I(t)/Cbat
2.) Ardunio:
Following is a pure virtual script, online compiler would not serve.
// Assume current coming from serial port
const float C_per_Ah = 3600;
// signal adjustment
const float current_scale_A = 0.1; // Ampere per serial step
const int current_offset = 128; // Offset of serial value for I=0A
float CBat_Ah = 94; /* Assumed Battery Capacity in Ah */
float Cbat_C = CBat_Ah * C_per_Ah; /* ... in Coulomb */
float SOC = 0.7; /* Initial State of Charge */
int incomingByte = current_offset; // for incoming serial data, initial 0 Ampere
float I = 0; /* current */
// the setup routine runs once when you press reset:
void setup()
{
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
// the loop routine runs over and over again forever:
void loop()
{
delay(1000); // wait for a second
if (Serial.available() > 0)
{
// read the incoming byte:
incomingByte = Serial.read();
}
I = (incomingByte-current_offset) * current_scale_A;
SOC = SOC + I/Cbat_C;
Serial.print("New SOC: ");
Serial.println(SOC, 4);
}
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.
Does anyone have an implementation of drand48() or an equivalent that can work in an OpenCL kernel?
I have been sending random numbers generated on the host through a buffer but I need random numbers generated on the device if there is any way to do this.
Here's an OpenCL device function which you can call from an OpenCL kernel:
uint rng_next(__global ulong *states, uint index) {
/* Assume 32 bits */
uint bits = 32;
/* Get current state */
ulong state = states[index];
/* Update state */
state = (state * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
/* Keep new state */
states[index] = state;
/* Return value */
return (uint) (state >> (48 - bits));
}
The states array contains the state of the PRNG for each work-item and the index is basically - but not necessarily - the work-item ID (which you can get with get_global_id()).
The states array can be generated in the host (using another PRNG) and copied to the device, or it can be initialized in the device using some kind of hash function applied to the work-item global IDs. If you use the work-item global IDs as initial seeds, the random streams for each work-item will be very low quality (due to high correlation between them). Here's a kernel to apply a hash function to decorrelate the initial seeds (note you need a main initial seed, passed by the host):
__kernel void rng_init(
const ulong main_seed,
__global clo_statetype *seeds) {
/* Get initial seed for this workitem. */
ulong seed = get_global_id(0) + main_seed;
/* Apply basic xor-shift hash, better ones probably exist. */
seed = ((seed >> 16) ^ seed) * 0x45d9f3b;
seed = ((seed >> 16) ^ seed) * 0x45d9f3b;
seed = ((seed >> 16) ^ seed);
/* Update seeds array. */
seeds[get_global_id(0)] = seed;
}
Note that, as pointed out in the comments, the drand48 is of very low quality, and if you use a lot of work-items you will see artifacts in your rendering. This post explains this in more detail.
This code is taken from the cl_ops library, which I'm the author of.
So I'm creating a code so that I can read and store temperature values
for at least 8hours and store it in the Arduino EEPROM. I also want the Built in LED to flash once every second, while the temperature sensor records once every minute. I wrote the following but I'm left with the LED staying on for a whole minute then off for another minute and so on. I want it to keep constantly flashing. I know it's because of my delay(6000) but I don't know how to fix it. Any help is appreciated, thanks!
#include <EEPROM.h> //Librería para controlar la EEPROM de la Arduino
float tempC; //Initialize variable for storing Temperature
int tempPin = 0; //Conected at A0
int addr = 0; //Cantidad de espacios (bytes) iniciales
int count = 0; //counter needed to stop at a certain point before overflowing the EEPROM memory
int Voltages[501]; // Array with space for 501 data Points.A little over 8 hours. Holding integer values of Voltages.
float Temps[501]; //Holds float values for Temperatures
const int SWITCH = 8; //set switch to port 8
int ledState = LOW; // ledState used to set the LED
unsigned long previousMillis = 0; // will store last time LED was updated
const long interval = 1000; // blink once per second
void setup(){
Serial.begin(115200);
pinMode(LED_BUILTIN,OUTPUT);
pinMode(SWITCH,INPUT_PULLUP);}
void loop(){
int i;
if (digitalRead(SWITCH)==HIGH & count<=501){
for (int i=0;i<EEPROM.length();i++){
EEPROM.write(i,0);} // Clears the EEPROM so that only new recorded values are shown. In case of terminating before 8h
Serial.println("-------Recording-------");
unsigned long currentMillis = millis(); // current time
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis; // save the last time the LED blinked
if (ledState == LOW) {// if the LED is off turn it on and vice-versa:
ledState = HIGH;} else {
ledState = LOW;}
digitalWrite(LED_BUILTIN, ledState);}
for (i=0; i<501; i++){
count = count+1;
int v = analogRead(tempPin); // reads voltage
Voltages[i] = v;
Serial.println(i);
Serial.println(Voltages[i]);
delay(60000);
EEPROM.put(addr, Voltages[i]); //stores voltages in EEPROM
addr= addr +2;}}
I think the solution you are looking for involves the use of timer interrupts. That would execute an interrupt service routine (might as well be a blinking led) regardless of what happens in the rest of your loop function. This might give you a better in-sight: Arduino timer interrupts
I can't get my pic24f04kl100 to turn on an LED at all. The below code is as simple as possible and it still doesn't turn on the LED on pin 6.
Code
#include <xc.h>
#define LED LATBbits.LATB4
#define LEDans ANSBbits.ANSB4
#define LEDtris TRISBbits.TRISB4
/* Setting up configuration bits */
_FOSCSEL(FNOSC_FRCPLL & IESO_OFF); // FRC w/PLL and int./ext. switch disabled
_FOSC(POSCMD_XT & FCKSM_CSECMD); // Pri. OSC XT mode and clk. switch on, fail-safe off
_FWDT(FWDTEN_OFF); // Watchdog timer off
void initialise();
void delay(int i);
void main() { // Main program loop
initialise(); // Intialise PIC
while (1) { // Infinite loop
LED = 1; // Set LED high
LED = 0; // Set LED low
}
}
void initialise() { // Configures the PIC
OSCCONbits.NOSC = 0b111; // Fast RC Oscillator with Postscaler and PLL module
delay(100);
CLKDIVbits.RCDIV = 0b000; // Set clock div 1:1
delay(100);
LEDans = 0;
delay(100);
LEDtris = 0; // Make LED an output
delay(100);
LED = 0; // Set LED low
}
void delay(int i) {
while(i--);
}
PICkit 3 Output
*****************************************************
Connecting to MPLAB PICkit 3...
Firmware Suite Version.....01.27.04
Firmware type..............dsPIC33F/24F/24H
Target detected
Device ID Revision = 0
The following memory area(s) will be programmed:
program memory: start address = 0x0, end address = 0x3ff
configuration memory
Programming...
Programming/Verify complete
By default B4 pin is analog. Configure it as digital by clearing the ANSB register, bit4
NOTE: Although clearing the bit DID NOT fix the problem. Moving to another pin (with less features) did. So I (fossum) made the assumption that this was at least on some level the correct answer.
The LED is blinking, but it's blinking very fast, try to put some delay between LED turn on and LED turn off.
Try this:
void main() { // Main program loop
initialise(); // Intialise PIC
while (1) { // Infinite loop
LED = 1; // Set LED high
delay(50000); //wait LED on time
LED = 0; // Set LED low
delay(50000); //wait LED off time
}
}