I am learning program AVR uCs.
An example code snippet contains this line:
DDRC |= (0 << 0) | (0 << 1); // PIN C0, C1 as input for buttons
I don't understand what sense
(0 << 0)
makes and in general what this line logically does.
I know what the DDRC is I only want to understand this logical operation.
May be the comment helps.
The code does nothing and might be wrong.
The author could have meant
DDRC |= (1 << 0) | (1 << 1);
which is short for
DDRC |= 3;
which reads the DDRC, sets the bottommost two bits, and writes that value back. The syntax using << and | attempts to make that clearer.
An alternative interpretation would be that the author intends to clear these two bits. In that case, the code is wrong, because it doesn't do that.
If the DDRC is the Data Direction Register for port C, chances are that writing a zero bit switches the direction to input, in which case the intention appears to be clearing the bits.
The appropriate code for that would be
DDRC &= ~( (1 << 0) | (1 << 1) );
Related
I have the assignment to create a running light on my Arduino with the following requirements/constraints
Requirements
Implement a socalled “runninglight” with 3 leds.
The on time of each led is the same, being 0.5 sec.
After the last Led is lit, the first starts again.
Constraints
The leds are connected to pin 8,9 and 10 of the Arduino. (don’t forget the resistors)
The running led must be implemented in the loop of the Arduino
The setup() function may contain any Arduino function/macro.
Only the Arduino function delay() is allowed in the loop.
No use of any other Arduino function/macro etc. in the loop.
No use of for/while in the loop() function
No use of your own defined functions
Your loop function must contain not more then 10 statements.
So in the loop you may only use
o Delay function
o Your variables
o The following characters/digits: * ( ) & ~ | ; = < > ! + - 0 1 2 3 4 5 6 7 8 9
I have tried the following code
#include <Arduino.h>
//mask for setting correct bits in register to setup leds to 1
#define DDBMASK 0x07
//masks for setting correct bits in register for led control to 1
#define LEDMASK 0x01
byte *ddBPtr; //point to ddB register (data direction)
byte *portBPtr; //point to portB resiger (data register)
void setup() {
//setup data direction register to set pins to output
ddBPtr = (byte *) 0x24;
*ddBPtr |= DDBMASK; // 0b0000 0111
//assign pointer to right register
portBPtr = (byte *) 0x25;
}
void loop() {
//use data register (portB) for controlling leds
*portBPtr ^= LEDMASK;
delay(500);
*portBPtr ^= LEDMASK;
*portBPtr ^= LEDMASK << 1;
delay(500);
*portBPtr ^= LEDMASK << 1;
*portBPtr ^= LEDMASK << 2;
delay(500);
*portBPtr ^= LEDMASK << 2;
}
Apparently this is possible with only one delay function and following the requirements and constrains. I have been stuck on this for hours and cant figure it out.
I tried the following which also does not work because I'm unable to reset my counter back to zero
void loop() {
//use data register (portB) for controlling leds
*portBPtr ^= (LEDMASK << ledCount);
delay(500);
*portBPtr ^= (LEDMASK << ledCount);
ledCount++;
//cant figure out a way to reset ledCount back to 0 after 3 itterations
//running light only runs once so first led does not light after third led is lit
}
What am I missing?
Perhaps this:
*portBPtr |= (1 << ledCount);
delay(500);
*portBPtr &= ~(1 << ledCount);
ledCount = (9 >> (ledCount << 1)) & 3;
This also avoids ^ which is not in your list of allowed symbols.
The line ledCount = (9 >> (ledCount << 1)) & 3 is like a lookup table with each entry taking up two bits. It maps 0 to 1, 1 to 2, 2 to 0. The normal way to write this code is ledCount = (1 + ledCount) % 3;
This might also work, being a little simpler:
delay(500);
*portBPtr = (1 << ledCount);
ledCount = (9 >> (ledCount << 1)) & 3;
By using assignment rather than | or & or ^, all the other bits will be zero, presumably causing the non-current leds to turn off.
So I have an assignment that wants me to perform certain code when a button on PD2 is presed.
The problem i'am having right now is i don't really know what to check for neither do
i understand the underlying logic.
So this is the code i've come up with thus far.
DDRD=0x00; //PORTD pin 0 as input
PORTD=0x00;
DDRB=0xFF; //PORTB as output
PORTB=0x00;
while(1){
if (PIND & (1<<PD2)==1) // check if PD2 is pressed on PIND2
{
// modify bits on PORTB here
}
}
I'm using Atmega328 and running this on AtmelStudio 7
To set PD2 to an input, run this C/C++ code, which clears bit 2 in register DDRD. There is no need to modify entire registers:
DDRD &= ~(1 << 2);
(You could skip this because every pin will be an input by default after the AVR resets.)
I don't know how you wired your button. If the button is wired between the pin and GND, and there is no external pull-up resistor to pull your pin high, then you should enable the internal pull-up after the pin is an input by running this code, which sets bit 2 in register PORTD:
PORTD |= 1 << 2;
Now to read the state of the button, you can use this C/C++ expression, which will evaluate to 0 if the pin is low or non-zero if the pin is high:
PIND & (1 << 2)
The expression below also works. It has the advantage of always evaluating to 0 or 1:
PIND >> 2 & 1
Here's some (untested) code that ties it all together, reading from PD2 and writing the value of PD2 to an output on PB3:
#include <avr/io.h>
int main()
{
// Make PD2 an input, pulled high.
DDRD &= ~(1 << 2);
PORTD |= 1 << 2;
// Make PB3 an output.
DDRB |= 1 << 3;
while (1)
{
if (PIND >> 2 & 1)
{
// PD2 is high, so drive PB3 high.
PORTB |= 1 << 3;
}
else
{
// PD2 is low, so drive PB3 low.
PORTB &= ~(1 << 3);
}
}
}
You might have to adapt the part of the code that deals with the output. I don't actually know what pin your output is on and what kind of behavior you want, so I just did something simple.
This code is full of the C bitwise operators. It is important for you to get a good book about C and learn exactly what those operators do, and this answer would be too long if I attempted to teach you all of them. Here is a list of operators for you to learn: <<, >>, &, &=, |, |=, ~.
unsigned char input_byte;
while(1){
__no_operation(); /* using nop for synchronization */
input_byte = PIND; /* read entire PIND */
}
This way you should be able to read your inputs every program cycle. But I've not tested this. It's important to use __no_operation() before reading again PIND.
I'm trying to learn how to write drivers for GPIO pins in STM32F4 Discovery. I was going through the tutorials and I came across this line:
static void hal_gpio_configure_pin_mode (GPIO_TypeDef *GPIOx, uint16_t pin_no, uint32_t mode)
{
GPIOx->MODER |= (mode << (2* pin_no));
}
I am relatively new to embedded systems and don't know what GPIOX->MODER |= (mode << (2* pin_no)); does. Also, I don't know why pin_no is 16 bit while mode is 32 bit. I know that << is the left shift bitwise operator. But I still don't get the complete context.
Can anybody explain all this?
Trying to explain the line GPIOx->MODER |= (mode << (2* pin_no));:
GPIOx is a pointer to a structure
GPIOx->MODER accesses the member MODER inside this structure
x |= y is an abbreviation of x = x | y, which means "perform a logic OR of x and y, and write the result back to x
mode << (2* pin_no) means left-shift the content of variable mode by twice pin_no bits.
Hence, the line means "take the content of GPIOx->MODER, bitwise-OR it with the left-shiftet content of mode.
I wrote a simple program to generate PWM wave with 50% duty cycle. Then I went for debugging in AtmelStudio. All registers except OCR0 were assigned there respective values. Why OCR0 not assigned any value.
ATmega32, Fast PWM.
#include <avr/io.h>
int main(void)
{
DDRB = (1 << PB3);
TCCR0 |= (1 << WGM01) | (1 << WGM00) | (1 << COM01);
OCR0 = 127;
TCCR0 |= (1 << CS02);
return 0;
}
So anyway.
You're using the 8-bit counter0 on your Atmega32. Let's see how you set it up:
// Set Pin B3 as output, others as input
DDRB = (1 << PB3);
// Set Clear on compare match + Fast PWM mode + Counter stopped
TCCR0 |= (1 << WGM01) | (1 << WGM00) | (1 << COM01);
// Set comparator value to 127
OCR0 = 127;
// Enable clkIO/256 from prescaler, turning on the counter
TCCR0 |= (1 << CS02);
Okay. First, a few things:
On initial setup, you usually want to assign the value and not or it, to be certain of its state.
Even after, setting it instead of or-ing it avoids a useless read. No impact on behavior for this register, but might be a bit better for performance.
The documentation recommends only enabling the output after you have set it up properly, to avoid spurious output. So you should move the first line last.
I'll be reading from that version of the datasheet.
Now, in fast PWM mode, according to table 38, and 40, the counter behaves like this:
It counts from BOTTOM to MAX (0 to 0xFF).
OCR0 is only used to toggle OC0 pin, not to reset the counting.
OCR0 has double-buffering. Its actual value is not updated until next cycle.
This might be your issue. If any of those are true:
Counter doesn't start properly (could happen if CS2-0 are not correct due to or-ing them instead of setting them).
Counter is stopped early (because your program ends and if the studio detects it, it could disable it at that point - I d'ont use the studio so I cannot really tell).
Then it is possible the value you write to the double buffer never makes it to the actual register. Alas the datasheet doesn't explain in detail how this is handled. Nor does it tell whether reading OCR0 while double buffering is active returns current value or awaiting value.
I want to read and write from/to an unsigned char according to the table below:
for example I have following variables:
unsigned char hsi_div = 0x01; /* HSI/2 */
unsigned char cpu_div = 0x05; /* Fmaster/32 */
I want to write hsi_div to bits 4,3 and cpu_div to bits 2,1,0 (imagine the whole char is named CLK_DIVR):
CLK_DIVR |= hsi_div << 4; //not correct!
CLK_DIVR |= cpu_div << 2; //not correct!
And lets say I want to read the register back to make sure I did it correct:
if( ((CLK_DIVR << 4) - 1) & hsi_div) ) { /* SET OK */ }
if( ((CLK_DIVR << 2) - 1) & cpu_div) ) { /* SET OK */ }
Is there something wrong with my bitwise operations!? I do not get correct behaviour.
I assume CLK_DIVR is a hardware peripheral register which should be qualified volatile. Such registers should be set up with as few writes as possible. You change all write-able bits, so just
CLK_DIVR = (uint8_t)((hsi_div << 3) | (cpu_div << 0));
Note using fixed width type. That makes mentioniong it is an 8 bit register unnecessary. According to the excerpt, the upper bits are read-only, so they are not changed when writing. The cast keeps the compiler from issuing a truncation warning which is one of the recommended warnings to always enable (included in -Wconversion for gcc).
The shift count is actually the bit the field starts (the LSbit). A shift count of 0 means "no shifting", so the shift-operator is not required. I still use it to clarify I meant the field starts at bit 0. Just let the compiler optimize, concentrate on writing maintainable code.
Note: Your code bit-or's whatever already is in the register. Bit-or can only set bits, but not clear them. Addiionally the shift counts were wrong.
Not sure, but if the excerpt is for an ARM Cortex-M CPU (STM32Fxxxx?), reducing external bus-cycles becomes more relevant, as the ARM can take quite some cycles for an access.
For the HSIDIV bit fields you want:
hw_register = (hw_register & 0x18) | (hsi_value & 0x03) << 0x03;
This will mask the value to 2 bits wide then shift to bit position 3 and 4.
The CPUDIV fields are:
hw_register = (hw_register & 0x7) | (cpu_value & 7);
Reading the register:
hsi_value = (hw_register & 0x18) >> 3;
cpu_value = hw_register & 0x07;
Just
CLK_DIVR |= hsi_div << 3;
CLK_DIVR |= cpu_div << 0;
Since hsi_div is a 2-digit binary, you have to move it three positions to skip the CPUDIV field. And the cpu_div is already at the end of the field.