Exemple UART sur STM8

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;
			}
		}
	}
}