USART ATmega328P - Programmation : Différence entre versions
(Page créée avec « {{Tutoriel |status_pub=Publié |image=Dsc08783.jpg |description=Exemple simple de communication USART |compétences requises=Débutant C/C++ |license=CC-by-sa-3.0 |contrib... ») |
|||
Ligne 70 : | Ligne 70 : | ||
<br/>(à compiler avec avr-gcc, le compilateur gcc dédiée au microcontrôleurs d'architecture AVR, et le téléverser dans le circuit intégré avec avrdude par exemple) | <br/>(à compiler avec avr-gcc, le compilateur gcc dédiée au microcontrôleurs d'architecture AVR, et le téléverser dans le circuit intégré avec avrdude par exemple) | ||
− | <br/>Ci-dessus, au début les directives pré-processeur des pointeurs des adresses des registres qui nous intéressent (voir [https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf fiche technique de l'ATmega328P]), | + | |
+ | <br/>Ci-dessus, au début les directives pré-processeur des pointeurs des adresses des registres qui nous intéressent (voir [https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf fiche technique de l'ATmega328P]), puis le vecteur d'interruption pour RXD, puis la définition d'une fonction générique d'interruption. | ||
<br/>Une fonction startUsart permet de démarrer l'USART avec le choix du baudrate (paramètre FREQUENCY), une fonction readUsart permet de dépiler ce qui arrive sur RXD, une fonction writeUsart permet d'envoyer des données sur TXD, et une fonction d'interruption (_INTERRUPT_JUMP) avec le bon vecteur d'interruption (_USART_RX) est exécutée lorsque des trames arrivent sur RXD (plus précisément à la fin d'un bit de stop). | <br/>Une fonction startUsart permet de démarrer l'USART avec le choix du baudrate (paramètre FREQUENCY), une fonction readUsart permet de dépiler ce qui arrive sur RXD, une fonction writeUsart permet d'envoyer des données sur TXD, et une fonction d'interruption (_INTERRUPT_JUMP) avec le bon vecteur d'interruption (_USART_RX) est exécutée lorsque des trames arrivent sur RXD (plus précisément à la fin d'un bit de stop). | ||
Ligne 78 : | Ligne 79 : | ||
<br/>Mais il est tout à fait possible d'aller plus vite, en effet la limite de l'ATmega328P est 2M bauds/s, vous pouvez donc remplacer 9600 par 2000000, la durée est donc maintenant de : | <br/>Mais il est tout à fait possible d'aller plus vite, en effet la limite de l'ATmega328P est 2M bauds/s, vous pouvez donc remplacer 9600 par 2000000, la durée est donc maintenant de : | ||
− | <br/>'''1000000 / (2000000 / 10) | + | <br/>'''1000000 / (2000000 / 10) = 5 µs''' |
<br/>Supposons une liaison RS232 à 115200 bauds/s, la durée est donc maintenant de : | <br/>Supposons une liaison RS232 à 115200 bauds/s, la durée est donc maintenant de : |
Version actuelle en date du 1 novembre 2021 à 03:21
Contributeur·ice·s
Status de la publication
Publié
License
CC-by-sa-3.0
Compétences requises
Bonjour à toute l'équipe PING.
Je souhaite apporter mon aide concernant la programmation C/C++ pour pouvoir faire communiquer votre ATmega328P (présent sur vos cartes Arduino UNO notamment) avec un ordinateur personnel via une liaison USART.
Exemple complet :
#define _SREG (*(volatile unsigned char *)(0x5f))
#define _UCSR0A (*(volatile unsigned char *)(0xc0))
#define _UCSR0B (*(volatile unsigned char *)(0xc1))
#define _UCSR0C (*(volatile unsigned char *)(0xc2))
#define _UBRR0LH (*(volatile unsigned int *)(0xc4))
#define _UDR0 (*(volatile unsigned char *)(0xc6))
#define _USART_RX __vector_ ## 18
#define _INTERRUPT_JUMP(vector) extern "C" void vector() __attribute__ ((signal)); void vector()
void startUsart (const unsigned long FREQUENCY)
{
_UCSR0A = 0b00000010;
_UCSR0B = 0b10011000;
_UCSR0C = 0b00000110;
_UBRR0LH = (16000000.0 / (8.0 * (float)(FREQUENCY))) - 0.5;
_SREG |= 0b10000000;
}
unsigned char readUsart()
{
while ((_UCSR0A & 0b10000000) != 0b10000000)
{
}
return _UDR0;
}
void writeUsart (const unsigned char DATA)
{
_UDR0 = DATA;
while ((_UCSR0A & 0b00100000) != 0b00100000)
{
}
}
_INTERRUPT_JUMP (_USART_RX)
{
readUsart();//données qui arrivent sur RXD
}
int main()
{
startUsart (9600);//démarrage de l'USART à 9600 bauds/s
while (true)
{
writeUsart (123);//le nombre 123 est envoyé sur TXD
}
return 0;
}
(à compiler avec avr-gcc, le compilateur gcc dédiée au microcontrôleurs d'architecture AVR, et le téléverser dans le circuit intégré avec avrdude par exemple)
Ci-dessus, au début les directives pré-processeur des pointeurs des adresses des registres qui nous intéressent (voir fiche technique de l'ATmega328P), puis le vecteur d'interruption pour RXD, puis la définition d'une fonction générique d'interruption.
Une fonction startUsart permet de démarrer l'USART avec le choix du baudrate (paramètre FREQUENCY), une fonction readUsart permet de dépiler ce qui arrive sur RXD, une fonction writeUsart permet d'envoyer des données sur TXD, et une fonction d'interruption (_INTERRUPT_JUMP) avec le bon vecteur d'interruption (_USART_RX) est exécutée lorsque des trames arrivent sur RXD (plus précisément à la fin d'un bit de stop).
Dans la fonction principale (main) la fonction startUsart est appelée avec en paramètre 9600, la vitesse de communication souhaitée (en bauds/s). À cette vitesse une communication dure :
1000000 / (9600 / 10) ≈ 1041 µs
Mais il est tout à fait possible d'aller plus vite, en effet la limite de l'ATmega328P est 2M bauds/s, vous pouvez donc remplacer 9600 par 2000000, la durée est donc maintenant de :
1000000 / (2000000 / 10) = 5 µs
Supposons une liaison RS232 à 115200 bauds/s, la durée est donc maintenant de :
1000000 / (115200 / 10) ≈ 86 µs
Cette communication RS232 passe par le port DE-9 de votre ordinateur personnel, son avantage est sa haute disponibilité. Il est également possible et souvent pratiqué de faire communiquer l'ATmega328P avec votre ordinateur personnel en USB via un composant FTDI.
Je me permets de citer wikipedia qui indique vulgairement des longueurs de câbles en fonction du nombre de bit/s (je ne sais pas si ils veulent évoquer le baud plutôt) via une liaison RS232 :
2400 bits/s = 60 mètres max
4800 bits/s = 30 mètres max
9600 bits/s = 15 mètres max
19200 bits/s = 7.6 mètres max
38400 bits/s = 3.7 mètres max
56000 bits/s = 2.6 mètres max
Donc, si dans vos projets avec un tel microcontrôleur de la famille des ATmega, vous constatez une lenteur dans votre boucle de calcul (que ce soit pour des applications robotique ou autre), et que vous utilisez des fonctions Arduino par exemple, il est important de dissocier matériel et logiciel, et de comprendre que la limitation ne vient la plupart du temps pas du matériel, mais bien du logiciel (Arduino) concernant cette liaison USART. Reposez vous la question : comment je programme mon microcontrôleur ? Ai-je la bonne méthotologie ? Les bons outils ? Le bon code source ? Le bon programme sur mon ordinateur personnel pour réceptionner les données émises par le microcontrôleur ?
Lorsque cette liaison USART est réglée avec une vitesse de 31250 bauds/s, elle peut servir à piloter des instruments de musique standards en MIDI en envoyant simplement 3 octets (status, data, et description), voir photos :
Dans tous les cas n'hésitez pas si vous avez des interrogations, besoin de plus de précisions, ou des suggestions à apporter.