Stark behov av hjälp med att skriva och ta emot av USART !
Re: Stark behov av hjälp med att skriva och ta emot av USART
^ Ah, smart där. Riktigt tacksam för hjälpen jag fått här ska ni veta!
Riktigt bra grej att kunna göra så där och debugga med lysdioder. Så nu har jag i alla fall tittat och i den första koden så kommer den bara till Receive-funktionen men den stannar när vid while-loopen. Jag har prövat och donat men det verkar alltså var som så att Receive Complete (RXC0) aldrig vill bli hög så den stannar där och jag kan inte ta kommunicera med den...?
Riktigt bra grej att kunna göra så där och debugga med lysdioder. Så nu har jag i alla fall tittat och i den första koden så kommer den bara till Receive-funktionen men den stannar när vid while-loopen. Jag har prövat och donat men det verkar alltså var som så att Receive Complete (RXC0) aldrig vill bli hög så den stannar där och jag kan inte ta kommunicera med den...?
Re: Stark behov av hjälp med att skriva och ta emot av USART
Muppis påpekade att det skrevs fel siffra i den första koden i USART_Init till UBRR0
Har du fixat det?
Har du fixat det?
Re: Stark behov av hjälp med att skriva och ta emot av USART
EDIT: Ah! Fick äntligen till det nu. Nu kan jag kommunicera med den riktig och få tillbaka som jag vill. 
Imorgon får jag börja testa skriva koden med tiden så där som Icecap visade, nu sömn,...

Imorgon får jag börja testa skriva koden med tiden så där som Icecap visade, nu sömn,...
Re: Stark behov av hjälp med att skriva och ta emot av USART
Kan nu kommunicera lite grann med mikrokontrollern, går att se på bilden och i koden här nedan.
Men nu är mitt problem alltså att jag vill kunna göra någonting med den där tiden som användaren ska skriva in på tangentbordet.
1. Jag ska en sträng som skriver till användaren "Enter time in hh:mm:ss". Det är nu fixat.
2. Sedan ska jag nu skanna av tidsvärdena från användarens värden för hh, mm och ss. Det fungerar också nu, mikrokontrollern läser och skriver tillbaka värdena nu till terminalprogrammet.
3. Efter det vill jag att tiden som användaren har tryckt in ska uppdatera sig och räkna upp precis som vilken annan digital klocka som helst, så någon form av beräkning ska jag ha.
Och här är jag alltså nu, jag har tittat på Icecaps exempel men det där sättet verkar lite för avancerat för mig just nu ärligt talat.
Någon idé eller tips här?
Alltså den ska bara få timmarna, minutrarna och sekunderna att uppdatera sig.

Men nu är mitt problem alltså att jag vill kunna göra någonting med den där tiden som användaren ska skriva in på tangentbordet.
1. Jag ska en sträng som skriver till användaren "Enter time in hh:mm:ss". Det är nu fixat.
2. Sedan ska jag nu skanna av tidsvärdena från användarens värden för hh, mm och ss. Det fungerar också nu, mikrokontrollern läser och skriver tillbaka värdena nu till terminalprogrammet.
3. Efter det vill jag att tiden som användaren har tryckt in ska uppdatera sig och räkna upp precis som vilken annan digital klocka som helst, så någon form av beräkning ska jag ha.
Och här är jag alltså nu, jag har tittat på Icecaps exempel men det där sättet verkar lite för avancerat för mig just nu ärligt talat.

Någon idé eller tips här?
Alltså den ska bara få timmarna, minutrarna och sekunderna att uppdatera sig.

Kod: Markera allt
#define F_CPU 16000000UL
#define BAUDRATE 19200
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
#include <avr/io.h>
#include <util/delay.h>
#include <inttypes.h>
//Deklarerar funktioner
void USART0_init();
void putchUSART0(unsigned char);
unsigned char getchUSART0(void);
void putsUSART0(char *str);
void getsUSART0(unsigned char *ptr);
void nylinje(void);
int BS = 0;
unsigned char ibuf[50];
int main(void)
{
int data;
USART0_init();
putsUSART0(" Enter the current time in this format hh:mm:ss");
nylinje();
nylinje();
putsUSART0(" Current time now is");
nylinje();
getsUSART0(&ibuf[0]);
nylinje();
data=getchUSART0();
putchUSART0(data);
while(1)
{
}
}
void USART0_init() // USART initialization
{
UBRR0L = 51;
UBRR0H = 0;
UCSR0A = 0x00;
UCSR0B = (1<<TXEN0)|(1<<RXEN0); //Slår på transmission och receive
UCSR0C = (0<<USBS0)|(3<<UCSZ00); // Frame: 8 bit, ingen paritet, 1 stopp bit.
}
void putchUSART0(unsigned char data) // Funktion for transmittera bit
{
while(!(UCSR0A & (1<<UDRE0))); // Vänta på att USART0s data register blir tomt
UDR0=data; // Sparar data i UDR0-register
}
unsigned char getchUSART0(void)
{
while (!(UCSR0A & (1<<RXC0))); //Väntar på att data ska tas emot
return UDR0; //Returnera sedan värderna som finns i UDR0
}
void putsUSART0(char *str)
{
while(*str){
putchUSART0(*str);
str++;
}
}
void nylinje(void) {
putchUSART0(0x0D); // ASCII-värdena för att göra en ny linje
putchUSART0(0x0A);
}
void getsUSART0(unsigned char *ptr)
{
char data;
while ((data = getchUSART0()) != 0x0D){
*ptr = data;
putchUSART0(data);
if (data == BS){
putchUSART0(0x0A);
putchUSART0(BS);
ptr--;
}
else ptr++;
}
*ptr = 0;
}
Re: Stark behov av hjälp med att skriva och ta emot av USART
Först och främst måste du se till att det finns en timer-interrupt som kan ge 1-sekund uppdatering.
Jag brukar att ha en "systemtimer" till lite av varje och den brukar ligga på allt mellan 10Hz och 1000Hz. I detta exempel utgår jag ifrån 10Hz.
Sedan har jag en räknare:
unsigned char Ctr;
I timer-interrupten:
Jag brukar att ha en "systemtimer" till lite av varje och den brukar ligga på allt mellan 10Hz och 1000Hz. I detta exempel utgår jag ifrån 10Hz.
Sedan har jag en räknare:
unsigned char Ctr;
I timer-interrupten:
Kod: Markera allt
if(++Ctr >= 10)
{
Ctr = 0;
if(++Second >= 60)
{
Second = 0;
if(++Minute >= 60)
{
Minute = 0;
if(++Hour >= 24) Hour = 0;
}
}
}
Re: Stark behov av hjälp med att skriva och ta emot av USART
Nu vet jag inte hur länge tideräkningen ska snurra men har för mig internklockan har en tolerans runt +-1%. Ska detta vara något som går år ut och år in så kan det vara idé att använda en temperaturkompenserad RTC och antingen hämta datum+klocka via seriegränssnittet eller någon utgång på RTC kopplad till ett ben på mcu med interrupt-on-change eller liknande.
Använder du 1000Hz som systemtimer så kan man också göra lite enkla justeringar för att kompensera driften, testa hur stabil 1000Hz genom att sätta ett IO-ben hög/lågt direkt i "timer interrupt"-rutinen och koppla scopet på IO-benet.
Använder du 1000Hz som systemtimer så kan man också göra lite enkla justeringar för att kompensera driften, testa hur stabil 1000Hz genom att sätta ett IO-ben hög/lågt direkt i "timer interrupt"-rutinen och koppla scopet på IO-benet.
Re: Stark behov av hjälp med att skriva och ta emot av USART
Helt korrekt med driften som opatagio påpekar. Och är det en klocka som ska gå över längre tid är en RTC (Real Time Clock) helt rätt den rätta väg att gå. Lägg till en supercap som backup och det fungerar bra.
Jag använder en DS3232 i det senaste projekt, just för att det är I²C som behövs även till EEPROM'en. Men för att göra det snabbt har jag skippat läsningen av RTC'n!
Detta gäller då under drift - men inte under uppstart. På DS323x finns en utgång som kan programmeras till att ge pulser ut och detta använder jag. Jag har programmerat den till att ge 1-sekunders pulser och när systemet startar läsas RTC-kretsen, tiden omvandlas till UNIX-tid (alltså en 32-bitars variabel med antal sekunder sedan ett visst datum) och när pulserna kommer till den externa interrupt räknar interruptrutinen (ISR) den systemtimer med 1.
Jag har sedan även en systemtimer på 1kHz körande och med lite programmering har jag fått den till att faslåsa till dessa 1-sekunders pulser så jag har en systemtid som är synkroniserat ner till 1ms upplösning.
Men denna synkronisering är nog lite överkurs för de flesta...
Jag använder en DS3232 i det senaste projekt, just för att det är I²C som behövs även till EEPROM'en. Men för att göra det snabbt har jag skippat läsningen av RTC'n!
Detta gäller då under drift - men inte under uppstart. På DS323x finns en utgång som kan programmeras till att ge pulser ut och detta använder jag. Jag har programmerat den till att ge 1-sekunders pulser och när systemet startar läsas RTC-kretsen, tiden omvandlas till UNIX-tid (alltså en 32-bitars variabel med antal sekunder sedan ett visst datum) och när pulserna kommer till den externa interrupt räknar interruptrutinen (ISR) den systemtimer med 1.
Jag har sedan även en systemtimer på 1kHz körande och med lite programmering har jag fått den till att faslåsa till dessa 1-sekunders pulser så jag har en systemtid som är synkroniserat ner till 1ms upplösning.
Men denna synkronisering är nog lite överkurs för de flesta...
Re: Stark behov av hjälp med att skriva och ta emot av USART
Ska lämna in om en timme. Om ni har några sista tips ni kan ge så här på koden så låt mig veta, vad som helst.
Den där funktionen med att uppdatera tiden fint struntar jag i, det hinner jag helt enkelt inte ordna på denna korta tid. Men jag tänker i alla fall pröva mig på en interrupt. Gärna feedback här med tanke på uppgiften om vad jag kunnat göra bättre och så.
Skulle nån se det här innan kl 00.00 och kan ge en hjälpande hand på hur jag kan göra interrupten, så vore det mer än uppskattat.


main.c
usart.h header
usart.c en extra c-modul
Den där funktionen med att uppdatera tiden fint struntar jag i, det hinner jag helt enkelt inte ordna på denna korta tid. Men jag tänker i alla fall pröva mig på en interrupt. Gärna feedback här med tanke på uppgiften om vad jag kunnat göra bättre och så.
Skulle nån se det här innan kl 00.00 och kan ge en hjälpande hand på hur jag kan göra interrupten, så vore det mer än uppskattat.


main.c
Kod: Markera allt
#define F_CPU 16000000UL
#define BAUDRATE 19200
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <inttypes.h>
#include <stdio.h>
#include "uart.h"
unsigned char buffer [50] = "";
int main(void)
{
unsigned char data;
USART_interrupt_init();
USART0_init(); // Step 1: Kallar på funktion som initialiserar USART0
putsUSART0(" Enter the current time in the format hh:mm:ss"); // Step 2: kallar på funktion som frågar om tiden
putchUSART0('\r');
putchUSART0('\n');
while(1)
{
getsUSART0(&buffer[0]); // Step 3: kallar på funktion för läsning av sträng från PC och sparar data i en buffer
data=getchUSART0();
putchUSART0('\n');
putsUSART0("Current time now is "); // Step 4: Skriver ut sträng och tid
for(;;){
putsUSART0(&buffer);
putchUSART0(data);
_delay_ms(1000); // Step 5 - Kallar på delay-funktionen och väntar 1s
putchUSART0('\r');
putchUSART0('\n');
}
}
}
Kod: Markera allt
#include <avr/io.h>
#ifndef UART_H_
#define UART_H_
//Deklarerar funktioner
void USART_interrupt_init();
void USART0_init();
void putchUSART0(unsigned char data); // Funktion som sänder en karaktär via serieporten
unsigned char getchUSART0(void);
void putsUSART0(char *str); // Funktion som sänder en string via serieporten
void getsUSART0(unsigned char *ptr);
#endif /* UART_H_ */
Kod: Markera allt
/*
#define F_CPU 16000000UL
#define BAUDRATE 19200
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <inttypes.h>
#include <stdio.h>
#include "uart.h"
void USART0_init() // USART0 initialisering
{
UBRR0L = 0x33; // Ger en baudrate på 19 200 bps
UBRR0H = 0x00;
UCSR0A = 0x00;
UCSR0B = (1<<TXEN0)|(1<<RXEN0); // Initialiserar transmission och receive
UCSR0C = (0<<USBS0)|(3<<UCSZ00); // Frame: 8 databit, ingen paritet, 1 stop bit
}
void putchUSART0(unsigned char data) // Funktion för att sända bit
{
while(!(UCSR0A & (1<<UDRE0))); // Vänta på att USART0s dataregister blir tomt
UDR0 = data; // Spara data i UDR0-register
}
unsigned char getchUSART0(void)
{
while (!(UCSR0A & (1<<RXC0))); // Vänta på at USART0s dataregister har mottagit samtliga bits
return UDR0; //Returnerar värden i UDR0
}
void putsUSART0(char *str)
{
while(*str){
putchUSART0(*str);
str++;
}
}
void getsUSART0(unsigned char *ptr)
{
char data;
while ((data = getchUSART0()) != 0x0D){
*ptr = data;
putchUSART0(data);
if (data == 0x08){
putchUSART0(0x0A);
putchUSART0(0x08);
ptr--;
}
else ptr++;
}
*ptr = 0;
}
void USART_interrupt_init(){
cli();
UBRR0L = 0x33; // Ger en baudrate på 19 200 bps
UBRR0H = 0x00;
UCSR0A = 0x00;
UCSR0B = ((1 << RXCIE0)|(1<<TXEN0)|(1<<RXEN0)); // Initialiserar transmission och receive
UCSR0C = (0<<USBS0)|(3<<UCSZ00); // Frame: 8 databit, ingen paritet, 1 stop bit
sei();
}
Re: Stark behov av hjälp med att skriva och ta emot av USART
Jaha - skoluppgift?!!! Det var ju en essentiell information som signifikant hade ändrat mina svar!
Re: Stark behov av hjälp med att skriva och ta emot av USART
^ Ha ajdå, det visste jag inte.
Men en annan fråga jag har om det här med kodning av mikrokontrollers är hur det egentligen skal definieras. Nästan överallt på nätet tycker jag mig se att folk definierar så här
ex 1. ska alltså sätta bit 1 på PORTB hög:
PORTB = (1 << PB1);
Men enligt andra så ska man sätta så här istället och ha en OR:
PORTB |= (1 << PB1);
Eller när man t. ex. ska "cleara" en bit 5 på PORTB så gör jag så här:
ex 2:
PORTB = (0 << PB5); istället för PORTB =~ (1 << PB5);
Men den senare ska tydligen vara mer korrekt, stämmer det verkligen? Och varför?
Ska man alltid använda en OR (|) när man ska ställa in en bit i ett register?
Och ska man alltid använda en NOT~ istället för att skriva typ (0 << bitnamnet); ?
Men en annan fråga jag har om det här med kodning av mikrokontrollers är hur det egentligen skal definieras. Nästan överallt på nätet tycker jag mig se att folk definierar så här
ex 1. ska alltså sätta bit 1 på PORTB hög:
PORTB = (1 << PB1);
Men enligt andra så ska man sätta så här istället och ha en OR:
PORTB |= (1 << PB1);
Eller när man t. ex. ska "cleara" en bit 5 på PORTB så gör jag så här:
ex 2:
PORTB = (0 << PB5); istället för PORTB =~ (1 << PB5);
Men den senare ska tydligen vara mer korrekt, stämmer det verkligen? Och varför?
Ska man alltid använda en OR (|) när man ska ställa in en bit i ett register?
Och ska man alltid använda en NOT~ istället för att skriva typ (0 << bitnamnet); ?
Re: Stark behov av hjälp med att skriva och ta emot av USART
PORTB = (1 << PB1);
Detta tilldelar hela PORTB värdet 0x02. Så använder du andra bits på PORTB till något pajar du med största sannolikhet det de gör.
PORTB |= (1 << PB1);
Tar värdet som PORTB har, OR in 0x02 och skriver tillbaka värdet till PORTB. Använder du PORTB till annat kommer det att vara oförändrat.
Samma med AND.
Och din clearing är bara dum! Att shifta en noll är fortfarande en noll.
PORTB =~ (1 << PB1);
sätter PORTB till 0xFD. I själva verket är "rätt" sätt att göra det på såhär:
PORTB &=~ (1 << PB1);
Detta tilldelar hela PORTB värdet 0x02. Så använder du andra bits på PORTB till något pajar du med största sannolikhet det de gör.
PORTB |= (1 << PB1);
Tar värdet som PORTB har, OR in 0x02 och skriver tillbaka värdet till PORTB. Använder du PORTB till annat kommer det att vara oförändrat.
Samma med AND.
Och din clearing är bara dum! Att shifta en noll är fortfarande en noll.
PORTB =~ (1 << PB1);
sätter PORTB till 0xFD. I själva verket är "rätt" sätt att göra det på såhär:
PORTB &=~ (1 << PB1);
Re: Stark behov av hjälp med att skriva och ta emot av USART
Anta att PORTB initialt är t ex 11110000
1<<PB1 = 00000010
I fall ett tilldelar du alltså PORTB värdet 00000010 varvid det initala värdet på övriga bitar försvann.
I fall två gör du 00000010 | 11110000 som blir 11110010 som läggs i PORTB. Det initiala värdet på övriga bitar kvarstår.
Fall två är alltså det korrekta sättet att göra det om du bara vill påverka PB1 i PORTB.
Edit: Icecap hann först.
1<<PB1 = 00000010
I fall ett tilldelar du alltså PORTB värdet 00000010 varvid det initala värdet på övriga bitar försvann.
I fall två gör du 00000010 | 11110000 som blir 11110010 som läggs i PORTB. Det initiala värdet på övriga bitar kvarstår.
Fall två är alltså det korrekta sättet att göra det om du bara vill påverka PB1 i PORTB.
Edit: Icecap hann först.
Re: Stark behov av hjälp med att skriva och ta emot av USART
Ah tack, uppfattat!
Då är det |= och &=~ som gäller.
Då är det |= och &=~ som gäller.
