Initialize the AD controller in IRQ mode - c++

I'm trying to understand initializing an ADC on the ARM Cortex M4 MK20DX256VLH7 on the Teensy 3.1. I'm curious about the terminology and relevant search terms as to what the symbols below mean. &= ~(3<<18), which I interpret as a bitwise AND on a bitwise NOT(3 bitwise left shift 18), means very little to me. I interpret what is inside the parenthetical as BIN 11 shifts to BIN 11000000000000000000. I understand that there is a pointer dereference happening to PINMODE1 (which is a little fuzzy to me) and that it is initializing pin 25 on the chip as an ADC input? I am not at all confident in my ability to parse this. Please advise. Thank you for your time.
void ADC_Init (void) {
LPC_PINCON->PINMODE1 &= ~(3<<18); /* P0.25 */
LPC_PINCON->PINMODE1 |= (1<<18); /* has neither pull-up nor pull-down */
LPC_PINCON->PINSEL1 &= ~(3<<18); /* P0.25 is GPIO */
LPC_PINCON->PINSEL1 |= (1<<18); /* P0.25 is AD0.2 */
LPC_SC->PCONP |= (1<<12); /* Enable power to ADC block */
LPC_ADC->ADCR = (1<< 2) | /* select AD0.2 pin */
(4<< 8) | /* ADC clock is 25MHz/5 */
(1<<16) | /* Burst mode */
(1<<21); /* enable ADC */
// LPC_ADC->ADINTEN = (1<< 8); /* global enable interrupt */
// NVIC_EnableIRQ(ADC_IRQn); /* enable ADC Interrupt */
}

Related

Canonical serial reading using terminos fail?

I am trying to read lines of datas comming from my arduino using serial.
My arduino code look like that : Serial3.print(Z, 2);Serial3.print(F(";"));Serial3.println(F("END\n"));
And this is my code to read the data on ubuntu :
void setup(){
//set up serial
tcgetattr(dueSerial, &port_options); // Get the current attributes of the Serial port
dueSerial = open("/dev/ttyUSB0", O_RDWR | O_NONBLOCK | O_NOCTTY | O_NDELAY);
if (dueSerial == -1) {
reportFailure("Could not open Arduino");
} else {
port_options.c_cflag &= ~PARENB; // Disables the Parity Enable bit(PARENB),So No Parity
port_options.c_cflag &= ~CSTOPB; // CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit
port_options.c_cflag &= ~CSIZE; // Clears the mask for setting the data size
port_options.c_cflag |= CS8; // Set the data bits = 8
port_options.c_cflag &= ~CRTSCTS; // No Hardware flow Control
port_options.c_cflag |= (CREAD | CLOCAL); // Enable receiver,Ignore Modem Control lines
port_options.c_iflag &= ~(IXON | IXOFF | IXANY); // Disable XON/XOFF flow control both input & output
port_options.c_lflag &= ~(ECHO | ECHONL | IEXTEN | ISIG); // no echo
port_options.c_iflag |= ICANON; //Enable canonical
port_options.c_iflag |= ICRNL; //map CR to NL
//port_options.c_oflag &= ~OPOST; // No Output Processing
//port_options.c_lflag = 0; // enable raw input instead of canonical,
/*
initialize all control characters
default values can be found in /usr/include/termios.h, and are given
in the comments, but we don't need them here
*/
port_options.c_cc[VINTR] = 0; /* Ctrl-c */
port_options.c_cc[VQUIT] = 0; /* Ctrl-\ */
port_options.c_cc[VERASE] = 0; /* del */
port_options.c_cc[VKILL] = 0; /* # */
port_options.c_cc[VEOF] = 4; /* Ctrl-d */
port_options.c_cc[VTIME] = 0; /* inter-character timer unused */
port_options.c_cc[VMIN] = 0; /* blocking read until 1 character arrives */
port_options.c_cc[VSWTC] = 0; /* '\0' */
port_options.c_cc[VSTART] = 0; /* Ctrl-q */
port_options.c_cc[VSTOP] = 0; /* Ctrl-s */
port_options.c_cc[VSUSP] = 0; /* Ctrl-z */
port_options.c_cc[VEOL] = 0; /* '\0' */
port_options.c_cc[VREPRINT] = 0; /* Ctrl-r */
port_options.c_cc[VDISCARD] = 0; /* Ctrl-u */
port_options.c_cc[VWERASE] = 0; /* Ctrl-w */
port_options.c_cc[VLNEXT] = 0; /* Ctrl-v */
port_options.c_cc[VEOL2] = 0; /* '\0' */
cfsetispeed( & port_options, BAUDRATE); // Set Read Speed
cfsetospeed( & port_options, BAUDRATE); // Set Write Speed
tcflush(dueSerial, TCIFLUSH);
tcflush(dueSerial, TCIOFLUSH);
int att = tcsetattr(dueSerial, TCSANOW, & port_options);
if (att != 0) {
reportFailure("ERROR in Setting Arduino port attributes");
} else {
LOG_INFO("SERIAL DUE Port Good to Go");
}
}
}
void UART::tick() {
//Arduino msg = "IMU;LAX;LAY;LAZ;AVX;AVY;AVZ;AY;AP;AR;END"
// rx_buffer[0] = '0';
memset(&rx_buffer, '\0', sizeof(rx_buffer));
// tcflush(dueSerial, TCIOFLUSH);
rx_length = read(dueSerial, &rx_buffer,255);
if (rx_length < 0) {
LOG_INFO("Error reading");
}else{
LOG_INFO("Read %i bytes. Received message: %s", rx_length, rx_buffer);
}
}
But when I try this code I get many lines at a time so my output look like this :
2020-11-15 09:13:09.491 INFO packages/skeleton_pose_estimation/apps/usb/UART.cpp#87: Read 0 bytes. Received message:
2020-11-15 09:13:09.496 INFO packages/skeleton_pose_estimation/apps/usb/UART.cpp#87: Read 255 bytes. Received message: 0.01;0.00;0.00;0.00;0.00;0.00;0.00;END
IMU;-0.00;0.02;0.03;0.00;0.00;0.00;0.00;0.00;0.00;END
IMU;-0.00;0.02;0.03;0.00;-0.00;0.00;0.00;0.00;0.00;END
IMU;-0.00;0.02;-0.02;0.00;-0.00;0.00;0.00;0.00;0.00;END
IMU;-0.00;0.02;-0.02;-0.00;0.00;0.00;0.00;0.00;
2020-11-15 09:13:09.501 INFO packages/skeleton_pose_estimation/apps/usb/UART.cpp#87: Read 241 bytes. Received message: 0.00;END
IMU;-0.01;-0.02;-0.01;-0.00;0.00;0.00;0.00;0.00;0.00;END
IMU;-0.01;-0.02;-0.01;-0.00;-0.00;0.00;0.00;0.00;0.00;END
IMU;-0.01;-0.02;0.03;-0.00;-0.00;0.00;0.00;0.00;0.00;END
IMU;-0.01;-0.02;0.03;0.00;0.00;0.00;0.00;0.00;0.00;END
2020-11-15 09:13:09.506 INFO packages/skeleton_pose_estimation/apps/usb/UART.cpp#87: Read 0 bytes. Received message:
2020-11-15 09:13:09.511 INFO packages/skeleton_pose_estimation/apps/usb/UART.cpp#87: Read 0 bytes. Received message:
But I want it to read only one line per read() function call.
I believe that I either set a wrong parameter making the conanical mode unused or maybe it's ignoring my \n and \r but don't know why....
Please help me to find why.
Thank you a ton !
But I want it to read only one line per read() function call. I believe that I either set a wrong parameter making the conanical mode unused ...
Your program does not behave as expected because canonical mode is never actually set.
The statement
port_options.c_iflag |= ICANON; //Enable canonical
is incorrect. ICANON is in the c_lflag member, and not in c_iflag.
Your code has additional issues.
(1) The variable dueSerial is used uninitialized:
void setup(){
//set up serial
tcgetattr(dueSerial, &port_options); // Get the current attributes of the Serial port
dueSerial = open(...);
...
The file descriptor needs to be obtained and validated before it can be used in the tcgetattr() call.
The proper ordering of statements is:
void setup(){
//set up serial
dueSerial = open(...);
if (dueSerial == -1) {
/* abort */
}
tcgetattr(dueSerial, &port_options);
...
(2) Numerous input conversions are left unspecified in your termios initialization.
Canonical mode enables various options to convert certain input characters, and most of these options need to be disabled for reading by a program (versus an interactive terminal).
Typically INPCK (enable input parity checking), IUCLC (map uppercase characters to lowercase), and IMAXBEL (ring bell when input queue is full) are disabled.
You need to review whether you also want IGNCR (preserve or ignore carriage return), INLCR (translate newline to carriage return), and ICRNL (translate carriage return to newline unless IGNCR is set) to also be disabled.
(3) Use of nonblocking mode is questionable.
Since you want "to read only one line per read() function call", then blocking mode is the proper way to obtain that result.
If you insist on using nonblocking mode, then the read() syscall will always return "immediately" and may not return any data at all.

ATMEGA16L Pull-up isn't active

i wan't to get Inputs to my Atmega16L from a Button. Ideally i can use the internal Pull-up's, so i don't have to attach them externally.
I've boiled down the code to the minimum:
void main(void) {
// SFIOR &= ~(1<<PUD); // Turn off Pull-up disable
DDRD = 0xFF; // Output PORT D
DDRA = 0x00; // Input PORT A
PORTA = 0xFF; // Pull-up on PORT A
_delay_ms(100);
while (1)
{
if (PINA & (1<<PA1)) // Check if PA0 is High
PORTD |= (1<<PD5); // Set PD5 to High
else
PORTD &= ~(1<<PD5); // Set PD5 to Low
}
return;}
I would expect, the Pin PD5 should be high, because the PA1 is pulled up by the internal pull-up, set on line 6.
But no, when i run the code, the Pin PD5 is low, and i have to connect the Pin PA1 to 5V, in order to get a High Signal on PD5.
Short things Short, it looks like the pull-up isn't active...
If tried working with the SFIOR, but the PUD is disabled by default, as far as i know.
kind regards,
Felix
EDIT: the requested Images:
On the photo you have AVCC power supply not connected (pin 30, against number 11 on the board). AVCC supplies power to ADC and port A. It should be always connected to VCC directly or via a noise filter, but should never be left floating.
Difference between VCC and AVCC should never exceed 0.3 V
Please read the pin descripton at page 5 of the datasheet

Linux blocking I/O doesn't work as expected

So I have a development board which has some UART peripherals muxed to some tty*-like files.
I have connected some other device on one port (RX pin), and I expect to be able to read the data that it was sent to me.
The devices sends me data in 11-bytes chunks.
This is the code I have been used:
if(-1 == (fd_read = open(port.c_str(), O_RDONLY))) {
throw std::ios_base::failure("Unable to open UART descriptor.");
}
tcgetattr(fd_read, &settings);
/*!
* Set some default settings.
*/
cfsetospeed(&settings, baud); /* baud rate */
settings.c_cflag &= ~PARENB; /* no parity */
settings.c_cflag &= ~CSTOPB; /* 1 stop bit */
settings.c_cflag &= ~CSIZE;
settings.c_cflag |= CS8 | CLOCAL; /* 8 bits */
settings.c_lflag = ICANON; /* canonical mode */
settings.c_oflag &= ~OPOST; /* raw output */
settings.c_cc[VMIN] = 0;
settings.c_cc[VTIME] = 0;
/*!
* Apply the settings for both: the writing and reading file descriptors.
*/
tcsetattr(fd_read, TCSANOW, &settings);
tcflush(fd_read, TCOFLUSH);
The problem is that the other devices sends me a data chunk (I can see it on scope), but the read() function doesn't return.
This is the read function call:
auto bytesReceived = ::read(fd_read, UARTDataBuffer, max_incoming_uart_data_length); // "max_incoming_uart_data_length" is 2048.
The strange thing is that when I use another TX pin from my board, and send the exact the same data (as I suppose to receive from the another device), everything works as expected, the read() function returns with the correct data.
Why is this happening?
L.E. More details about the problem:
Both, the development board (BeagleBone Black) and the other sensor are using 3.3V for UART signals.
After configuring the communication with the code shown above, I also applied the following command on the associated tty*-like file:
stty -F /dev/ttyO2 921600
Where /dev/ttyO2 is my UART-associated port, and 921600 is the baud rate value.
I use this because termios structure don't provide such higher baud values.
I'm expecting that stty won't change the other settings (like parity, start/stop bits, etc), it will only set the baud rate.
Update2: When I open the same port (where I'm expecting data) using minicom, everything works as expected, I'm able to receive data in my application. (and the minicom also captures the data).

Interrupt with KL25Z board using KDS

I am programming a microcontroller using Kinetis Design Studio(KDS) and i want to implement an interrupt such that at anytime during runtime if a specific I/O pin has a "high" level the microcontroller should stop working until the pin is back to "low" .
Any ideas?
Try this code from free scale forum
https://www.element14.com/community/community/designcenter/kinetis_kl2_freedom_board/blog/2015/08/21/kinetis-design-studio-30-kinetis-sdk-12-processor-expert-using-frdm-kl43z-quick-tutorial-on-gpio-interrupt-toggling-led-using-button-with-interrupt-logic
or
below is an usart interrupt code you can modify it
/* p6_4.c UART0 Receive using interrupt */
/* This program modifies p4_2.c to use interrupt to handle the UART0 receive.
Receiving any key from terminal emulator (TeraTerm) of the host PC to the UART0 on Freescale FRDM-KL25Z board.
UART0 is connected to openSDA debug agent and has a virtual connection to the host PC COM port.
Launch TeraTerm on a PC and hit any key.
The LED program from P2_7 of Chapter 2 is used to turn on the tri-color LEDs according to the key received.
By default in SystemInit(), FLL clock output is 41.94 MHz.
Setting BDH=0, BDL=0x17, and OSR=0x0F yields 115200 Baud. */
#include <MKL25Z4.H>
void UART0_init(void);
void delayMs(int n);
void LED_init(void);
void LED_set(char value);
int i=0;
int main (void) {
__disable_irq(); /* global disable IRQs */
UART0_init();
LED_init();
__enable_irq(); /* global enable IRQs */
while (1) {
/* UART0 receive is moved to interrupt handler*/
}
}
/* UART0 interrupt handler */
void UART0_IRQHandler(void)
{
char c;
c = UART0->D; /* read the char received */
LED_set(c); /* and use it to set LEDs */
}
/* initialize UART0 to receive at 115200 Baud */
void UART0_init(void)
{
SIM->SCGC4 |= 0x0400; /* enable clock for UART0 */
SIM->SOPT2 |= 0x04000000; /* use FLL output for UART Baud rate generator */
UART0->C2 = 0; /* turn off UART0 while changing configurations */
UART0->BDH = 0x00;
UART0->BDL = 0x17; /* 115200 Baud */
UART0->C4 = 0x0F; /* Over Sampling Ratio 16 */
UART0->C1 = 0x00; /* 8-bit data */
UART0->C2 = 0x24; /* enable receive and receive interrupt*/
NVIC->ISER[0] |= 0x00001000; /* enable INT12 (bit 12 of ISER[0]) */
SIM->SCGC5 |= 0x0200; /* enable clock for PORTA */
PORTA->PCR[1] = 0x0200; /* make PTA1 UART0_Rx pin */
}
/* initialize all three LEDs on the FRDM board */
void LED_init(void)
{
SIM->SCGC5 |= 0x400; /* enable clock to Port B */
SIM->SCGC5 |= 0x1000; /* enable clock to Port D */
PORTB->PCR[18] = 0x100; /* make PTB18 pin as GPIO */
PTB->PDDR |= 0x40000; /* make PTB18 as output pin */
PTB->PSOR |= 0x40000; /* turn off red LED */
PORTB->PCR[19] = 0x100; /* make PTB19 pin as GPIO */
PTB->PDDR |= 0x80000; /* make PTB19 as output pin */
PTB->PSOR |= 0x80000; /* turn off green LED */
PORTD->PCR[1] = 0x100; /* make PTD1 pin as GPIO */
PTD->PDDR |= 0x02; /* make PTD1 as output pin */
PTD->PSOR |= 0x02; /* turn off blue LED */
}
/* turn on or off the LEDs according to bit 2-0 of the value */
void LED_set(char value)
{
if (value=='c')
{ /* use bit 1 of value to control green LED */
PTB->PCOR = 0x80000; /* turn on green LED */
s }
if (~(value=='c') )
{ /* use bit 1 of value to control green LED */
PTB->PSOR = 0x80000; /* turn off green LED */
}
}

GPIO mode register

I've adjusted the example from here for the STM3240G-EVAL board in order to blink LEDs 3 and 4. I have it working, but am confused by the Mode register setting:
GPIOG->MODER |= (GPIO_MODER_MODER6_0 | GPIO_MODER_MODER8_0) ;
When I read the reference manual (p186), it claims that the mode must be set to 01 for output, yet setting it to 0 in this way works just fine. Ideally I'd like to be able to change to the other modes, but I would have assumed that the above code would have changed pins 6 and 8 of port G to input pins. I must be missing something.
Here's my complete main document in case it's relevant:
#include "stm32f4xx.h"
/* We will use PG6 and PG8 connected to LEDs 1 and 2 because they're the same port. */
/* Find base register value for Port G */
void delay (int a);
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f0xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f0xx.c file
*/
/* GPIOG Periph clock enable */
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN;
GPIOG->MODER |= (GPIO_MODER_MODER6_0 | GPIO_MODER_MODER8_0) ;
/* Configure PG6 and PG8 in output mode */
GPIOG->OTYPER &= ~(GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_8) ;
// Ensure push pull mode selected--default
GPIOG->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR6|GPIO_OSPEEDER_OSPEEDR8);
//Ensure maximum speed setting (even though it is unnecessary)
GPIOG->PUPDR &= ~(GPIO_PUPDR_PUPDR6|GPIO_PUPDR_PUPDR8);
//Ensure all pull up pull down resistors are disabled
while (1)
{
/* Set PG6 and PG8 */
/* the bit set/reset low register SETS the output data register */
/* the bit set/reset high register RESETS the output data register */
GPIOG -> BSRRL = (1 << 6);
GPIOG -> BSRRL = (1 << 8);
delay(500000);
/* Reset PC8 and PC9 */
GPIOG -> BSRRH = (1 << 6);
GPIOG -> BSRRH = (1 << 8);
delay(500000);
}
return 0;
}
void delay (int a)
{
volatile int i,j;
for (i=0 ; i < a ; i++)
{
j++;
}
return;
}
You aren't setting it to zero, you're setting it to one.
The definition of the GPIO_MODER_MODER6_0 constant is 0x00001000. The mask for the GPIO_MODER_MODER6 bits is 0x00003000, so you're putting bits 01 into the right place.
If the constant GPIO_MODER_MODER6_0 were defined as zero, then or'ing it into the configuration register would have no effect in any case. To set both bits to zero you'd need to do something like:
GPIOG->MODER &= ~(GPIO_MODER_MODER6_0 | GPIO_MODER_MODER6_1);
The _0 and _1 suffixes refer to the bit numbers for masking, not the values being written.