Exemple UART sur STM8
Pile
1/12/2019
Établissement d'une liaison série
Afin de pouvoir opérer avec le plus haut débit, on sélectionne l'horloge extérieure qui nous permet d'atteindre une fréquence de 16MHz
Code exemple
/* MAIN.C file
*
* Copyright (c) 2002-2019 PhL
*/
// Utilisation d'un timer en direct
#include "stm8s.h"
#include "fonctions_TP_utiles.h"
#define LED_VERTE 0x01
#define DUREE 62501
//#define DUREE 20000
#define MSK_TXE 0x80
#define MSK_TC 0x40
#define MSK_RXNE 0x20
#define MSK_0R 0x08
u8 val;
u8 cnt;
void ClockInit( void)
{
// Version utilisant HSE
CLK->ECKR = 0; // Reset the External Clock Register.
CLK->ECKR |= CLK_ECKR_HSEEN; // Enable the HSE.
CLK->ICKR = 0; // Disable the internal clock.
while( (CLK->ECKR & CLK_ECKR_HSERDY) == 0); // Wait for the HSE to be ready for use.
CLK->CKDIVR = 0; // Ensure the clocks are running at full speed.
CLK->PCKENR1 = 0xff; // Enable all peripheral clocks.
CLK->PCKENR2 = 0xff; // Ditto.
CLK->CCOR = 0; // Turn off CCO.
CLK->SWIMCCR = 0; // Set SWIM to run at clock / 2.
CLK->SWR = 0xb4; // Use HSE as the clock source.
CLK->SWCR = 0; // Reset the clock switch control register.
CLK->SWCR |= CLK_SWCR_SWEN; // Enable switching.
while( (CLK->SWCR & CLK_SWCR_SWBSY));// Pause while the clock switch is busy.
}
main()
{
// Initialisation
ClockInit();
// Timer 3
// Periode d'update de 1 s
// PSCR P.Pscr Durée maximale
// 0 0.5µs
// 1 1µs 0,065s
// 2 2µs
// 3 4µs
// 4 8µs 0,524s
// 5 16µs 1,048576
// ARR = (1 / 0.000016)+1 = 62500+1
TIM3->PSCR = 5;
TIM3->ARRH = DUREE >> 8;
TIM3->ARRL = DUREE & 0xFF;
TIM3->CR1 |= TIM3_CR1_CEN;
// UART2
// Debit 115200 avec fMasgter à 16MHz:
// ATTENTION toujours affecter BRR2 avant BRR1
UART2->BRR2 = 0x0a;
UART2->BRR1 = 0x08;
// R8 T8 UARTD M WAKE PCEN PS PIEN
// 0 0 0 1 0 1 0 0
UART2->CR1 = 0x10 | 0x04; // M 8bits, PCEN parity control
// TIEN TCIEN RIEN ILIEN TEN REN RWU SBK
// 0 0 0 0 >1 >1 0 0
UART2->CR2 = 0x0C; // Receive & Transmit enabled
// res LINEN STOP STOP CLKEN CPOL CPHA LBLC
// 0 0 0 0 0 0 0 0
UART2->CR3 = 0x00; // 1 Stop bit
// DDR: 0 input, 1 output
GPIOD->DDR = 0x01;
// CR1-INPUT: 0 Floating, 1 Pull-up; CR1-OUTPUT: 0 Open drain, 1 Push-pull
GPIOD->CR1 = 0x0;
// CR2-INPUT: 0 sans interrupt, 1 avc interrupt; CR2-OUTPUT: 0 Speed 2MHz, 1 Speed 10MHz
GPIOD->CR2 = 0x00;
val = 0x00; // Rien a transmettre
cnt = 0;
while (1) {
// Toutes les secondes on envoit un caractere
if( TIM3->SR1 & TIM3_SR1_UIF) {
if( GPIOD->ODR & LED_VERTE)
GPIOD->ODR &= ~LED_VERTE;
else GPIOD->ODR |= LED_VERTE;
TIM3->SR1 &= ~TIM3_SR1_UIF;
cnt++;
if( cnt > 9) cnt = 0;
val = 0x30 | cnt;
//val = 0x55;
}
// Sur reception d'un octet on l'echote decale de 1
if( UART2->SR & MSK_RXNE) {
// Un caractere a ete recu
val = UART2->DR; // ce qui remet RXNE a 0
val++;
}
if( val > 0) {
// un caractere est a transmettre
if( UART2->SR & MSK_TXE) {
// Tx est vide on ecrit l'octet
UART2->DR = val;
val = 0;
}
}
}
}