Modify the AVR C program - avr

I need to modify the code in this picture so that the LED I have connected to bit 7 of PORT D blinks only when both the switches are on. I have a switch connected to bit 5 of PORT D as well. This is where the on-board LED is for my arduino. I am totally stuck. AVR C Program

I assume your led is on D.7 and switch on (active low) D.4 and D.5 (i dont know why PORT B mentioned on your code.
unsigned char x;
int main(void)
DDRD = 0b10000000;
PORTD = 0b00110000; //activate internal pull just in case
x=PIND;
x&=0b00110000; // just in case (again)
if (x&0b00110000)
{
PORTD = 0b11000000; //blinks
_delay_ms (500);
PORTD = 0b00000000; //blinks
_delay_ms (500);
}
}

Related

how to flush write to raspberry pi gpio pins

I have a program written in C++ on a Raspberry Pi 3. I mmap /dev/gpiomem to access the GPIO registers directly in user mode. Here is my function to write to output pins:
static uint32_t volatile *gpiopage; // initialized by mmap() of /dev/gpiomem
static uint32_t lastretries = 0;
void PhysLib::writegpio (uint32_t value)
{
uint32_t mask = 0xFFF000; // [11:00] input pins
// [23:12] output pins
// all the pins go through an inverter converting the 3.3V to 5V
gpiopage[GPIO_CLR0] = value;
gpiopage[GPIO_SET0] = ~ value;
// sometimes takes 1 or 2 retries to make sure signal gets out
uint32_t retries = 0;
while (true) {
uint32_t readback = ~ gpiopage[GPIO_LEV0];
uint32_t diff = (readback ^ value) & mask;
if (diff == 0) break;
if (++ retries > 1000) {
fprintf (stderr, "PhysLib::writegpio: wrote %08X mask %08X, readback %08X diff %08X\n",
value, mask, readback, diff);
abort ();
}
}
if (lastretries < retries) {
lastretries = retries;
printf ("PhysLib::writegpio: retries %u\n", retries);
}
}
Apparently there is some internal cache or something delaying the actual updating of the pins. So I'm wondering if there is some magic MRC or MCR or whatever that I can put so I don't have to read the pins to wait for the update to actually occur.
I'm quite sure this is happening because this code is part of a loop:
while (true) {
writegpio (0x800000); // set gpio pin 23
software timing loop for 1uS
writegpio (0); // clear gpio pin 23
software timing loop for 1uS
}
Sometimes Linux timeslices during the software timing loops on me and I get a delay longer than 1uS, which is ok for this project. Before I put in the code that loops until it reads the updated bit, sometimes the voltage on the pin stays high for longer than 1uS and is then low for correspondingly less than 1uS, or vice versa, implying that there is a total of 2uS delay for the two timing loops but the update of the actual pin is being delayed by the hardware. After inserting the corrective code, I always get at least 1uS of high voltage and 1uS of low voltage each time through the loop.

Unable to use ADC on atmega328

I am trying to make a proximity sensor using ATmega328P. I am using the onboard ADC to convert the voltage value and if it is higher than the ambient, an LED is lit.
The voltage that is being sensed is according to this circuit:
In the circuit, the VOUT is going to ADC channel 3 and should be sensed (think of the led on the right as the IR Sensor).
When the program starts, it senses 30 readings and takes their average to be used as the ambient setting. If any subsequent measurement is higher than this value, the LED should be lit.
But the LED does not light even if I place my hand above the sensor.
I have tested with just the LED to see if the IR sensor is ok. It is ok by the way.
The code for the microcontroller is as follows:
/*
* Proximity Sensor IR.c
*
* Created: 6/3/2017 2:35:33 PM
* Author : Rishav
*/
#include <avr/io.h>
#include <stdio.h>
#define F_CPU 16000000UL
#include <util/delay.h>
int calibration()
{
unsigned int sum = 0;
for (int i=0; i<30; i++)
{
ADCSRA |= (1<<ADSC);
while(!(ADCSRA & (1<<ADIF)));
ADCSRA |= (1<<ADIF);
sum += (ADCH<<8)|ADCL;
}
return (sum/30);
}
int main(void)
{
unsigned int val = 0;
ADMUX |= (0<<REFS1)|(1<<REFS0)|(0<<MUX3)|(0<<MUX2)|(1<<MUX1)|(1<<MUX0); //setting the multiplexer to ADC3
ADCSRA |= (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
DDRB = 0b00000010;
DDRD |= (1<<PCINT22);
PORTD |= (1<<PCINT22);
int calib_value = calibration();
while (1)
{
ADCSRA |= (1<<ADSC);
while(!(ADCSRA & (1<<ADIF)));
val = (ADCH<<8)|ADCL;
ADCSRA |= (1<<ADIF);
if (val > calib_value)
PORTB = 0b00000010;
}
}
I think there is some problem in the code. Please help.
Some things that come to mind when looking at your code:
You are really not completely initializing the ADMUX and ADCSRA registers - everything you put in there is just 'ORed'-in. (ADLAR in ADMUX is not in a defined state, for example, ADCSRA has even more undefined bits).
After setting the reference voltage source in the ADMUX register, you are supposed to wait for the chip to switch, but don't. Most probably, your first measurement in calibration will be way off. The simplest way to address this is to do one first measurement whose result you simply ignore. (or wait some ms after you have set up ADC).
You are supposed to always read ADCL before ADCH (the AVR locks the ADC for writing further results to the result register when ADCL is read until ADCH is read as well). Your current code has an undefined read order of those 2 registers.
You have to enable the ADC first and select channel and reference voltage afterwards. It is easy to skip this fact in the datasheet.
The ADC is enabled by setting the ADC Enable bit, ADEN in ADCSRA.
Voltage reference and input channel selections will not go into effect
until ADEN is set. Datasheet page 238.
I did not check all of your settings but I am pretty sure that this must be your issue.
Example order:
void init_adc()
{
ADCSRA |= (1<<ADEN); // enable ADC
ADMUX |= (1<<MUX1) | (1<<MUX0); // channel selection ADC3 - PB3
ADMUX &= ~(1<<REFS0); // VCC as reference
ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // setting prescaler to 128
}
As mentioned a you should read ADCL first to:
ADCL must be read first, then ADCH, to ensure that the content of the
Data Registers belongs to the same conversion
I suggest to move this part into a separate function like:
uint16_t read_adc()
{
ADCSRA |= (1<<ADSC);
while(!(ADCSRA & (1<<ADIF)));
uint8_t adcl = ADCL;
uint8_t adch = ADCH;
ADCSRA |= (1<<ADIF);
return (adch<<8) | adcl;
}

ATMega2560 PCINT Interrupts

i am new to Atmel, so maybe the question is quite simple.
I have the following situation:
I have an ATMega2560 and want to get Interrupts on the Pins PK0-PK7. I am interested in the PIN Change from Low to HIGH. (I have connected one photocell to every PIN)
I have read that the interrupt for PCINT[0-2] are fired everytime (pin high and pin low) so i defined an array to ignore the PIN DOWN Interrupt.
So i have the following code:
Note: I do not understand, why i need to set DDRC as input and not DDRK ?
#define HIGH 1
#define LOW 0
volatile uint8_t portbhistory = 0xFF;
uint8_t pinState[8];
void initSystem()
{
int i;
for(i = 0; i < sizeof(pinState) / sizeof(*pinState); i++)
{
pinState[8] = 0;
}
DDRB = 0xff; // set Port B as output
DDRC = 0; // WHY DDRC ?? PCINT == PK0-7, so DDRK ? // all Pins input
PORTC = 0xff; // same question ... // turn on pullup for every pin
PCICR |= _BV(PCIE2); // enable interrupt for PCIE2
PCMSK2 = 0xff; // Interrupt at all pins
sei(); // turn on interrupts
}
int main(void)
{
initSystem();
while(1)
{
}
}
ISR(PCINT2_vect)
{
int i;
uint8_t changedbits;
changedbits = PINC ^ portbhistory;
portbhistory = PINC;
/*
if(pinState[changedbits] == HIGH)
{
pinState[changedbits] = LOW;
return;
} else
{
pinState[changedbits] = HIGH;
}
*/
setDebugLED(1);
_delay_ms(30);
setDebugLED(0);
}
If i connect 5V to one of the PINS (PK0-7) the LED flashes instantly. But if i disconnect the 5V it takes ~2seconds for the LED to flash again. In this time the one pin i connected 5V before does not let the LED flash again if i connect the 5 V again.
Other Ports work in this time.
So you could say, that the PIN HIGH interrupt for all pins work fine and get fired instantly but the PIN LOW interrupts need some time (~2sec.) In this time the port is "disabled" or somethig.
Can anyone help me with that?
EDIT
Just some wrong edit ...
EDIT 2
So, i totally forgot to post my solution here. sorry for that!
The solution is: My external circuit pulls the PIN to Ground or to 5V.
Thank you!

ATtiny84 pwm led flicker

I'm fairly new to avr programming and I'm trying to simply fade 3 leds independently connected to ATtiny84 pwm pins. Right now I have code that should chnage brightness of two different leds. Here is my code:
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRB |= (1 << PB2); // PWM output on PB2
TCCR0A = (1 << COM0A1) | (1 << WGM00); // phase correct PWM mode
OCR0A = 0x10; // initial PWM pulse width
TCCR0B = (1 << CS01); // clock source = CLK/8, start PWM
DDRA |= (1<<PA6); // make OC1A (DDA6) PWM output pin
TCCR1A = (1<<COM1A1) | (1<<COM1B0) | (1<<WGM00); // Clear OC1A/OC1B on Compare Match (bit 7 + 6)
// PWM, Phase Correct
TCCR1B = (1<<CS02); // 256 prescaler
while(1)
{
// change PWM pulse width every 2 seconds
_delay_ms(2000);
OCR0A = 0x10;
OCR1A = 0x10;
_delay_ms(2000);
OCR0A = 0x30;
OCR1A = 0x30;
_delay_ms(2000);
OCR0A = 0x50;
OCR1A = 0x50;
_delay_ms(2000);
OCR0A = 0xA0;
OCR1A = 0xA0;
}
}
The code is mostly copied from internet and I don't really understand the initializations, but now the led connected to PB2 works fine but the one connected to PA6 is not working right. PA6 led does change its brightness accordingly but it also flickers on and off rapidly (about 10 times a second).
First I thought it had something to do with PA6 being also MOSI pin for programming but disconnecting programmer didn't help.
Any help is appreciated! Also any tips for avr programming in general are more than welcome!
Just in case you haven't had a look yet, this is the relevant datasheet for your microcontroller: ATtiny84 Datasheet. Looking at the TCCR* timer configuration registers might reveal something.

Smallest (code-wise) bit - banged serial interface on PIC10

I need to interface to a PIC10 micro with some serial interface. Since these small devices lack hardware support for SPI I2C and UART a Software solution is inevitable.
However, since I need to preserve as much of the Programm memory to store (static) configuration and identify information to be retrieved via said interface, what would probably be the smallest solution?
I will need to program this in ASM since there seems no good C compiler for PIC10. However, this will be my first real encounter with ASM to speak of.
Try this download which contains code samples and says:
"Listed below are five PIC UART software routines to use with PIC microprocessors that have no hardware UART"
Link rot has broken the original link try this link.
In my opinion the xc8 compiler works pretty well, also for the PIC10.
Here is an example in C:
#include <xc.h>
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 4000000
#endif
#define Baudrate 1200 //bps
#define OneBitDelay (1000000/Baudrate)
#define DataBitCount 8 // no parity, no flow control
#define UART_RX RA1 // UART RX pin
#define UART_TX RA0 // UART TX pin
#define UART_RX_DIR TRISA1 // UART RX pin direction register
#define UART_TX_DIR TRISA0 // UART TX pin direction register
//Function Declarations
void InitSoftUART(void);
unsigned char UART_Receive(void);
void UART_Transmit(const char);
__CONFIG(FOSC_INTOSC & MCLRE_OFF & WDTE_OFF & LVP_OFF & CP_OFF &
WRT_OFF & PWRTE_OFF & WRT_OFF & BOREN_ON & LPBOR_ON & BORV_LO);
void main()
{
unsigned char ch = 0;
ANSELA = 0x00; // Set ports as digital I/O, not analog input
ADCON = 0x00; // Shut off the A/D Converter
FVRCON = 0x00; // Shut off the Voltage Reference
PORTA = 0x00; // Make all pins 0
InitSoftUART(); // Intialize Soft UART
InitSoftUART(); // Intialize Soft UART
while(1)
{
ch = UART_Receive(); // Receive a character from UART
UART_Transmit(ch); // Echo back that character
}
}
void InitSoftUART(void) // Initialize UART pins to proper values
{
UART_TX = 1; // TX pin is high in idle state
UART_RX_DIR = 1; // Input
UART_TX_DIR = 0; // Output
}
unsigned char UART_Receive(void)
{
// Pin Configurations
// GP1 is UART RX Pin
unsigned char DataValue = 0;
//wait for start bit
while(UART_RX==1);
__delay_us(OneBitDelay);
__delay_us(OneBitDelay/2); // Take sample value in the mid of bit duration
for ( unsigned char i = 0; i < DataBitCount; i++ )
{
if ( UART_RX == 1 ) //if received bit is high
{
DataValue += (1<<i);
}
__delay_us(OneBitDelay);
}
// Check for stop bit
if ( UART_RX == 1 ) //Stop bit should be high
{
__delay_us(OneBitDelay/2);
return DataValue;
}
else //some error occurred !
{
__delay_us(OneBitDelay/2);
return 0x000;
}
}
void UART_Transmit(const char DataValue)
{
/* Basic Logic
TX pin is usually high. A high to low bit is the starting bit and
a low to high bit is the ending bit. No parity bit. No flow control.
BitCount is the number of bits to transmit. Data is transmitted LSB first.
*/
// Send Start Bit
UART_TX = 0;
__delay_us(OneBitDelay);
for ( unsigned char i = 0; i < DataBitCount; i++ )
{
//Set Data pin according to the DataValue
if( ((DataValue>>i)&0x1) == 0x1 ) //if Bit is high
{
UART_TX = 1;
}
else //if Bit is low
{
UART_TX = 0;
}
__delay_us(OneBitDelay);
}
//Send Stop Bit
UART_TX = 1;
__delay_us(OneBitDelay);
}
Source for this code is the :Microchip forum

Resources