Hello everyone,
I am in need of some programming help, because I am lacking experience and tricks using the AVR programmed in C.
I am prototyping a level attenuator, which is using two 4051 cmos ics controlled by a 4094 shift register, to form 64 steps of attenuation. The analog side works as intended, but I have problems controlling the shift register. In the schematic I planned on using 74HC595 registers, but the only thing I had around at the moment just for proof of concept was a 4094. I want to feed it with its data (a simple 6-bit value) via the SPI interface of the Atmega preferably. Some code has already been programmed by me, with plenty of room for improvement, but it is constantly sending out the data. But it should only put out the shifted data once it is done shifting, so it doesn´t transport the spi frequency to my analog signal. It doesn´t need to be fast, since it only has to set the attenuation once through a user interface. (For testing I added two buttons, one to increase and one to decrease the stored value).
I do find tutorials on how to use them with an AVR but I can´t get my head around to that, because everybody seems to have their own functions programmed. Is there a clean version, like a clean function to simply transmit serial data to a shift register simply by giving it the value it has to send? Should I use a timer to make it cleaner?
For some additional information, the finished product will have 7 or 8 of these attenuators controlled by one SPI bus by cascading all the required shift registers together and sending out a long word of data.
I attach some pictures so it is easier to understand what I´m up to.
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
void SPI_MasterInit(void)
{
DDRB |= (1<<2)|(1<<3)|(1<<5);
PORTB |= (1<<2);
SPCR = (1<<SPIE)|(1<<SPE)|(1<<MSTR)|(1<<CPOL)|(0<<CPHA)|(1<<SPR0)|(1<<SPR1);
}
void SPI_MasterTransmit(char cData)
{
SPDR = cData;
while(!(SPSR & (1<<SPIF)))
;
}
int main(void)
{
PORTD = 0x00;
DDRD &= 0xFC;
PORTD = (1<<0) | (1<<1);
PORTC = 0x00;
DDRC = 0xff;
int data = 0x00;
SPI_MasterInit();
/* Replace with your application code */
while (1)
{
if ((PIND & (1<<0)) == 0)
{
_delay_ms(250);
data++;
}
if ((PIND & (1<<1)) == 0)
{
_delay_ms(250);
data--;
}
if (data >= 0x40)
{
data = 0x00;
}
PORTC = data;
SPI_MasterTransmit(data);
}
If you need more information let me know.
The 4094 is wired up to the MOSI, SCK and SS lines as it is showed in many examples. On my little board it is the three pin headers in the middle and on my AVR board it is the three free pins on the right.
Thank you in advance!:)