uart #11

Merged
stud126165 merged 4 commits from uart into dev 2024-02-06 07:32:16 +00:00
9 changed files with 164 additions and 127 deletions

36
UART/circular_buf.c Normal file
View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h>
#include "circular_buf.h"
void initialize_buffer(struct circular_buffer* cb) {
cb->buf_head = 0;
cb->buf_tail = 0;
}
// Проверка, пустой ли буфер
int buffer_empty(const struct circular_buffer* cb) {
return cb->buf_head == cb->buf_tail;
}
// Проверка, заполнен ли буфер
int buffer_full(const struct circular_buffer* cb) {
return (cb->buf_tail + 1) % BUFFER_SIZE == cb->buf_head; //проверяем следующее число, если оно будет совпадать с индексом головы то будет false, при совпадении вывод true
}
// Запись в буфер
void write_buffer(struct circular_buffer* cb, int value) {
if (buffer_full(cb)) { // проверяем, заполнен ли буфер
return;
}
cb->buffer[cb->buf_tail] = value;// записываем значение в элемент массива в хвост
cb->buf_tail = (cb->buf_tail + 1) % BUFFER_SIZE;// присваивается cb->buf_tail, обновляется его значение на следующий индекс в буфере
}
// Чтение элемента
int read_buffer(struct circular_buffer* cb) {
if (buffer_empty(cb)) { // проверка на пустоту
return -1;// -1 как индикатор в случае ошибки
}
int value = cb->buffer[cb->buf_head]; // чтение по индексу головы
cb->buf_head = (cb->buf_head + 1) % BUFFER_SIZE; // увеличиваем индекс на 1
return value;
}

18
UART/circular_buf.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef CIRCULAR_BUFFER_H
#define CIRCULAR_BUFFER_H
#define BUFFER_SIZE 32
struct circular_buffer{
unsigned char buffer[BUFFER_SIZE];
unsigned char buf_head;
unsigned char buf_tail;
};
void initialize_buffer(struct circular_buffer* cb);
int buffer_empty(const struct circular_buffer* cb);
int buffer_full(const struct circular_buffer* cb);
void write_buffer(struct circular_buffer* cb, int value);
int read_buffer(struct circular_buffer* cb);
#endif /* CIRCULAR_BUFFER_H */

21
UART/timer.c Normal file
View File

@ -0,0 +1,21 @@
#include <avr/io.h>
#include <avr/interrupt.h>
static volatile unsigned long timerMillis = 0;
void timerInit() {
TCCR1B |= (1 << WGM12) | (1 << CS11) | (1 << CS10);
OCR1A = 250;
TIMSK1 |= (1 << OCIE1A);
sei();
}
unsigned long millis() {
unsigned long ms;
ms = timerMillis;
return ms;
}
ISR(TIMER1_COMPA_vect) {
timerMillis++;
}

7
UART/timer.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef TIMER_H
#define TIMER_H
void timerInit();
unsigned long millis();
#endif // TIMER_H

64
UART/uart.c Normal file
View File

@ -0,0 +1,64 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <string.h>
#include "timer.h"
#include "circular_buf.h"
#include "uart.h"
void UART_init(void) {
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0) | (1 << UDRIE0); // прерывание по приему и опустошению буфера передачи
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
UBRR0H = 0;
UBRR0L = 103;
}
void UART_send(uint8_t* data, size_t length) {
for (size_t i = 0; i < length; i++) {
if (!buffer_full(&usartTxBuffer)) {
write_buffer(&usartTxBuffer, data[i]);
} else {
break; // если буфер передачи заполнен, то отправка прерывается
}
}
UCSR0B |= (1 << UDRIE0); // Включаем прерывание по опустошению буфера
}
// Получение данных из буфера
int UART_receive(uint8_t* data, size_t length) {
char overflow=0; // Флаг переполнения, который устанавливается, если превышен размер массива
uint32_t byteCount=0; // Счетчик байтов, принятых из буфера приема
uint32_t timeout_ms = 4; // Таймаут в миллисекундах для общего времени приема данных
uint32_t start_time = millis();
//Цикл приема данных с таймаутом
while(1)
{
// Пока буфер приема не пуст и не истек таймаут общего времени,
// функция продолжает читать байты из буфера и сохранять их в массив data.
while (!buffer_empty(&usartRxBuffer)) {
int reader = read_buffer(&usartRxBuffer);//прием и запись символа в переменную
if(byteCount<=length){
data[byteCount] = reader; // запись в массив с индексом byteCount
}
else{
overflow=1;
}
byteCount++;
start_time = millis();
}
if ((millis() - start_time) > timeout_ms) { // если превышение времени в 4 ms
break;
}
}
return overflow?-1:byteCount; // возвращает количество успешно принятых байт или -1
}
// прерывание по завершению приема
ISR(USART_RX_vect) {
uint8_t data = UDR0; // читаем из регистра UDR0
if (!buffer_full(&usartRxBuffer)) {
write_buffer(&usartRxBuffer, data);// записываем символ в буфер приема
}
}

18
UART/uart.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef UART_H
#define UART_H
#include <stdint.h>
#include <stddef.h>
#include "timer.h"
#include "circular_buf.h"
#define F_CPU 16000000
struct circular_buffer usartRxBuffer;
struct circular_buffer usartTxBuffer;
void UART_init(void);
void UART_send(uint8_t* data, size_t length);
int UART_receive(uint8_t* data, size_t length);
#endif /* UART_H */

25
main.c
View File

@ -1,25 +0,0 @@
#include <stdint.h>
#include "config.h"
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "uart_hal.h"
int main(void)
{
//example
uint8_t data = 'A';
uart_init(9600,0);
uart_send_byte(data);
sei();
while (1)
{
if(uart_read_count() > 0){
data = uart_read();
uart_send_byte(data);
}
}
}

View File

@ -1,82 +0,0 @@
#include "uart_hal.h"
volatile static uint8_t rx_buffer[RX_BUFFER_SIZE] = {0};
volatile static uint16_t rx_count = 0;
volatile static uint8_t uart_tx_busy = 1;
// кольцевой буффер
ISR(USART_RX_vect){
volatile static uint16_t rx_write_pos = 0;
rx_buffer[rx_write_pos] = UDR0;
rx_count++;
rx_write_pos++;
if(rx_write_pos >= RX_BUFFER_SIZE){
rx_write_pos = 0;
}
}
ISR(USART_TX_vect){
uart_tx_busy = 1;
}
void uart_init(uint32_t baud,uint8_t high_speed){
uint8_t speed = 16;
if(high_speed != 0){
speed = 8;
UCSR0A |= 1 << U2X0;
}
baud = (F_CPU/(speed*baud)) - 1;
UBRR0H = (baud & 0x0F00) >> 8;
UBRR0L = (baud & 0x00FF);
UCSR0B |= (1 << TXEN0) | (1 << RXEN0) | (1 << TXCIE0) | (1 << RXCIE0);
}
void uart_send_byte(uint8_t c){
while(uart_tx_busy == 0);
uart_tx_busy = 0;
UDR0 = c;
}
void uart_send_array(uint8_t *c,uint16_t len){
for(uint16_t i = 0; i < len;i++){
uart_send_byte(c[i]);
}
}
void uart_send_string(uint8_t *c){
uint16_t i = 0;
do{
uart_send_byte(c[i]);
i++;
}while(c[i] != '\0');
uart_send_byte(c[i]);
}
uint16_t uart_read_count(void){
return rx_count;
}
uint8_t uart_read(void){
static uint16_t rx_read_pos = 0;
uint8_t data = 0;
data = rx_buffer[rx_read_pos];
rx_read_pos++;
rx_count--;
if(rx_read_pos >= RX_BUFFER_SIZE){
rx_read_pos = 0;
}
return data;
}

View File

@ -1,20 +0,0 @@
#ifndef UART_HAL_H_
#define UART_HAL_H_
#include <stdint.h>
#include "config.h"
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define RX_BUFFER_SIZE 128
void uart_init(uint32_t baud,uint8_t high_speed);
void uart_send_byte(uint8_t c);
void uart_send_array(uint8_t *c,uint16_t len);
void uart_send_string(uint8_t *c);
uint16_t uart_read_count(void);
uint8_t uart_read(void);
#endif /* UART_HAL_H_ */