#include <stdio.h>
#include <math.h>
#include <avr/io.h>
#include <util/delay.h>
#define NUM_READINGS 10
#define USART_BAUDRATE 9600
#define ADC_CHANNEL 0
#define UBRR_VALUE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
#define PORT_ON(port,pin) port |= (1<<pin)
#define PORT_OFF(port,pin) port &= ~(1<<pin)
// първо декларираш всички функции
void USART0Init(void);
void USART0SendByte(char u8Data, FILE *stream);
void InitADC(void);
uint16_t ReadADC(uint8_t ADCchannel);
float ReadAndReturnAVG(uint8_t channel, uint16_t *values, int sizeOfValues);
// сега идват дефинициите на функциите
void USART0Init(void)
{
// Set baud rate
UBRR0H = (uint8_t)(UBRR_VALUE>>8);
UBRR0L = (uint8_t)UBRR_VALUE;
// Set frame format to 8 data bits, no parity, 1 stop bit
UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00);
//enable transmission and reception
UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
}
// функция, която винаги връща 0 няма нужда да връща нищо
// за това сменяме на void
void USART0SendByte(char u8Data, FILE *stream)
{
if(u8Data == '\n')
{
USART0SendByte('\r', stream);
}
//wait while previous byte is completed
while(!(UCSR0A&(1<<UDRE0))){};
// Transmit data
UDR0 = u8Data;
}
//set stream pointer
FILE usart0_str = FDEV_SETUP_STREAM(USART0SendByte, NULL, _FDEV_SETUP_WRITE);
void InitADC(void)
{
// Select Vref=AVcc
ADMUX |= (1<<REFS0);
//set prescaller to 128 and enable ADC
ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADEN);
}
uint16_t ReadADC(uint8_t ADCchannel)
{
//select ADC channel with safety mask
ADMUX = (ADMUX & 0xF0) | (ADCchannel & 0x0F);
//single conversion mode
ADCSRA |= (1<<ADSC);
// wait until ADC conversion is complete
while( ADCSRA & (1<<ADSC) );
return ADC;
}
/*
* Фунцкията приема като първи параметър канала от който ще чете
* Вторият параметър е указател към масива, в който ще запишем стойностите (uint16_t *values)
* Tъй като ReadADC ни връща uint16_t, то и стойностите в масива ще са от този тип.
* Накрая катваме на функцията колко голям е масива,който и подаваме, защото това при
* 'C' не може да се определи по време на изпълнение на програмата
*/
float ReadAndReturnAVG(uint8_t channel, uint16_t *values, int sizeOfValues) {
int i = 0;
int total = 0;
float average = 0.0f;
for (i = 0; i < sizeOfValues; i++) {
values[i] = ReadADC(channel); // тука може да ползваме функцията ReadADC,защото
// тя вече е декларирана най-отгоре и е позната
total = total + values[j]; // няма нужда от екстра loop за сбора
_delay_ms(500);
}
average = (float)total / (float)sizeOfValues;
return average;
}
int main() {
DDRB = 0xff; // Set Port B as Output
PORTB = 0x00;
//initialize ADC
InitADC();
//Initialize USART0
USART0Init();
//assign our stream to standard I/O streams
stdout = &usart0_str;
uint16_t values[NUM_READINGS] = {0};
float average = 0.0f;
while(1)
{
average = ReadAndReturnAVG(ADC_CHANNEL, values, NUM_READINGS);
printf("Average: %d\n", (int)(round
(average
))); // кастваш закръглената стойност към int // и си спестяваш линкване на float за printf
/**
// ако искаш може да изкараш всички стойности от последното четене
// Те са запаметени в масива, който подаваме на функцията
printf("Readings {\n");
int j = 0;
for(j = 0; j < NUM_READINGS; j++) {
printf(" [%d] %d\n", j, values[j]);
}
printf("}\n\n");
*/
}
}