Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная 7.docx
Скачиваний:
0
Добавлен:
20.12.2025
Размер:
351.4 Кб
Скачать

Министерство науки и высшего образования Российской Федерации

Федеральное государственное автономное образовательное учреждение высшего образования

ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ СИСТЕМ УПРАВЛЕНИЯ И РАДИОЭЛЕКТРОННИКИ (ТУСУР)

Кафедра комплексной информационной безопасности электронно-вычислительных систем (КИБЭВС)

ВНЕШНИЕ ИНТЕРФЕЙСЫ МИКРОКОНТРОЛЛЕРА

Отчет по лабораторной работе №7

по дисциплине «Основы программирования микроконтроллеров»

Вариант №4

Студенты гр. 712-2: ___________ Л.С. Болтушкин

___________ Н.А. Рыбин

___________ Д.В. Шабанова __________

Руководитель Старший преподаватель кафедры КИБЭВС

_______ __________ Д.С. Беляков

__________

Томск 2025

Введение

Целью данной лабораторной работы является углубленное изучение архитектуры ARM на примере микроконтроллера STM32F103RBT6, изучение межпроцессного взаимодействия в OCPB FreeRTOS и интерфейсов микроконтроллера.

Вариант №4 – Скорость работы UART - 115200. Один поток считывает раз в 200 мс значение температуры или давления и отправляет его через очередь во второй поток. Второй поток выводит данные значения с их единицами измерения в консоль. Тип значения меняется одинарным нажатием на кнопку.

1 Ход работы

Для выполнения данной лабораторной работы были использованы файлы, созданные в предыдущей лабораторной работе.

Рисунок 1.1 – Использованные файлы

Выполнена инициализация интерфейса UART (USART2) для организации обмена данными с ПК через виртуальный COM-порт. В соответствии с вариантом 4, скорость передачи была установлена на 11520 бод. Были настроены выводы PA2 и PA3, после чего реализована и интегрирована в проект функция для отправки текстовых сообщений в терминал.

После этого осуществлена полная инициализация датчика BME280: установлены режимы измерения, коэффициенты усреднения и фильтрации. Реализованы функции чтения калибровочных коэффициентов и получения измеренных значений температуры, влажности и давления с применением алгоритмов компенсации.

В соответствии с заданием варианта 4 была разработана многопоточная программа на базе существующего проекта FreeRTOS, включающая два потока.

После был создан файл «main.c», результат выполнения кода представлен на рисунке 1.2.

Код программы представлен в приложении А.

Рисунок 1.2 – Результат выполнения программы

Заключение

В ходе выполнения лабораторной работы были углубленно изучены архитектура микроконтроллера STM32F103RBT6 и основы работы с внешними интерфейсами UART и SPI в среде ОСРВ FreeRTOS. Были получены практические навыки настройки и использования данных интерфейсов, а также организации межзадачного взаимодействия с помощью очередей сообщений.

Приложение а

(обязательное)

Листинг кода файла «main.c»

#include "FreeRTOS.h"

#include "task.h"

#include "queue.h"

#include "stm32f1xx.h"

#include <stdint.h>

/* ==================== КОНСТАНТЫ ==================== */

#define SYSTEM_CLOCK 8000000

#define UART_BAUD_RATE 115200

#define LED_PIN 5 // PA5

#define BUTTON_PIN 13 // PC13

/* BME280 registers */

#define BME280_ID_REG 0xD0

#define BME280_CTRL_HUM 0xF2

#define BME280_CTRL_MEAS 0xF4

#define BME280_CONFIG 0xF5

#define BME280_TEMP_MSB 0xFA

#define BME280_PRESS_MSB 0xF7

/* ==================== RTOS ==================== */

typedef struct {

uint8_t type; // 0-temp, 1-pressure

int32_t value;

} sensor_data_t;

QueueHandle_t sensor_queue;

/* ==================== BME280 CALIB ==================== */

static uint16_t dig_T1;

static int16_t dig_T2, dig_T3;

static uint16_t dig_P1;

static int16_t dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9;

static int32_t t_fine;

/* ==================== GLOBAL ==================== */

volatile uint8_t measure_mode = 0; // 0-temp, 1-pressure

/* ==================== UART ==================== */

static void init_uart(void) {

RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;

RCC->APB1ENR |= RCC_APB1ENR_USART2EN;

GPIOA->CRL &= ~(GPIO_CRL_MODE2 | GPIO_CRL_CNF2);

GPIOA->CRL |= GPIO_CRL_MODE2 | GPIO_CRL_CNF2_1;

GPIOA->CRL &= ~(GPIO_CRL_MODE3 | GPIO_CRL_CNF3);

GPIOA->CRL |= GPIO_CRL_CNF3_0;

GPIOA->ODR |= (1 << 3);

USART2->BRR = SYSTEM_CLOCK / UART_BAUD_RATE;

USART2->CR1 |= USART_CR1_TE | USART_CR1_UE;

}

static void uart_send_char(char c) {

while (!(USART2->SR & USART_SR_TXE));

USART2->DR = c;

}

static void uart_send_string(const char *s) {

while (*s) uart_send_char(*s++);

}

/* ==================== SPI ==================== */

static void init_spi(void) {

RCC->APB2ENR |= RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN;

RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;

GPIOB->CRH &= ~(GPIO_CRH_MODE13 | GPIO_CRH_CNF13);

GPIOB->CRH |= GPIO_CRH_MODE13 | GPIO_CRH_CNF13_1;

GPIOB->CRH &= ~(GPIO_CRH_MODE14 | GPIO_CRH_CNF14);

GPIOB->CRH |= GPIO_CRH_CNF14_0;

GPIOB->CRH &= ~(GPIO_CRH_MODE15 | GPIO_CRH_CNF15);

GPIOB->CRH |= GPIO_CRH_MODE15 | GPIO_CRH_CNF15_1;

GPIOB->CRL &= ~(GPIO_CRL_MODE1 | GPIO_CRL_CNF1);

GPIOB->CRL |= GPIO_CRL_MODE1;

GPIOB->BSRR = (1 << 1);

SPI2->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_1 |

SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_SPE;

}

static uint8_t spi_transfer(uint8_t d) {

while (!(SPI2->SR & SPI_SR_TXE));

SPI2->DR = d;

while (!(SPI2->SR & SPI_SR_RXNE));

return SPI2->DR;

}

static void spi_read(uint8_t reg, uint8_t *buf, uint8_t len) {

GPIOB->BRR = (1 << 1);

spi_transfer(reg | 0x80);

for (uint8_t i = 0; i < len; i++) buf[i] = spi_transfer(0);

GPIOB->BSRR = (1 << 1);

}

static void spi_write(uint8_t reg, uint8_t val) {

GPIOB->BRR = (1 << 1);

spi_transfer(reg & 0x7F);

spi_transfer(val);

GPIOB->BSRR = (1 << 1);

}

/* ==================== BME280 ==================== */

static void bme280_calibrate(void) {

uint8_t d[24];

spi_read(0x88, d, 6);

dig_T1 = (d[1]<<8)|d[0];

dig_T2 = (d[3]<<8)|d[2];

dig_T3 = (d[5]<<8)|d[4];

spi_read(0x8E, d, 18);

dig_P1 = (d[1]<<8)|d[0];

dig_P2 = (d[3]<<8)|d[2];

dig_P3 = (d[5]<<8)|d[4];

dig_P4 = (d[7]<<8)|d[6];

dig_P5 = (d[9]<<8)|d[8];

dig_P6 = (d[11]<<8)|d[10];

dig_P7 = (d[13]<<8)|d[12];

dig_P8 = (d[15]<<8)|d[14];

dig_P9 = (d[17]<<8)|d[16];

}

static void bme280_init(void) {

uint8_t id;

spi_read(BME280_ID_REG, &id, 1);

spi_write(BME280_CTRL_HUM, 0x01);

spi_write(BME280_CTRL_MEAS, 0x27);

spi_write(BME280_CONFIG, 0xA0);

bme280_calibrate();

}

static int32_t bme280_get_temperature(void) {

uint8_t d[3];

spi_read(BME280_TEMP_MSB, d, 3);

int32_t adc = (d[0]<<12)|(d[1]<<4)|(d[2]>>4);

int32_t v1 = ((((adc>>3)-(dig_T1<<1)))*dig_T2)>>11;

int32_t v2 = (((((adc>>4)-dig_T1)*((adc>>4)-dig_T1))>>12)*dig_T3)>>14;

t_fine = v1+v2;

return (t_fine*5+128)>>8; // *100

}

static uint32_t bme280_get_pressure(void) {

uint8_t d[3];

spi_read(BME280_PRESS_MSB, d, 3);

int32_t adc = (d[0]<<12)|(d[1]<<4)|(d[2]>>4);

int64_t v1 = ((int64_t)t_fine)-128000;

int64_t v2 = v1*v1*(int64_t)dig_P6;

v2 += ((v1*(int64_t)dig_P5)<<17);

v2 += (((int64_t)dig_P4)<<35);

v1 = ((v1*v1*(int64_t)dig_P3)>>8)+((v1*(int64_t)dig_P2)<<12);

v1 = (((((int64_t)1)<<47)+v1)*dig_P1)>>33;

if (!v1) return 0;

int64_t p = 1048576-adc;

p = (((p<<31)-v2)*3125)/v1;

return (uint32_t)(p>>8)/100;

}

/* ==================== BUTTON ==================== */

static void init_button(void) {

RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;

GPIOC->CRH &= ~(GPIO_CRH_MODE13 | GPIO_CRH_CNF13);

GPIOC->CRH |= GPIO_CRH_CNF13_1;

GPIOC->ODR |= (1 << 13);

}

static void init_exti(void) {

RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

AFIO->EXTICR[3] |= AFIO_EXTICR4_EXTI13_PC;

EXTI->IMR |= EXTI_IMR_MR13;

EXTI->FTSR |= EXTI_FTSR_TR13;

NVIC_EnableIRQ(EXTI15_10_IRQn);

}

void EXTI15_10_IRQHandler(void) {

if (EXTI->PR & EXTI_PR_PR13) {

EXTI->PR = EXTI_PR_PR13;

measure_mode ^= 1;

}

}

/* ==================== TASKS ==================== */

static void sensor_task(void *arg) {

sensor_data_t d;

while (1) {

d.type = measure_mode;

d.value = (measure_mode == 0)

? bme280_get_temperature()

: bme280_get_pressure();

xQueueSend(sensor_queue, &d, portMAX_DELAY);

vTaskDelay(pdMS_TO_TICKS(200));

}

}

static void print_number(int32_t n) {

char b[10]; int i=0;

if (n==0) { uart_send_char('0'); return; }

if (n<0){ uart_send_char('-'); n=-n; }

while(n){ b[i++]=n%10+'0'; n/=10; }

while(i--) uart_send_char(b[i]);

}

static void processor_task(void *arg) {

sensor_data_t d;

while (1) {

if (xQueueReceive(sensor_queue, &d, portMAX_DELAY)) {

if (d.type == 0) {

uart_send_string("Temperature: ");

print_number(d.value/100);

uart_send_char('.');

print_number(d.value%100);

uart_send_string(" C\r\n");

} else {

uart_send_string("Pressure: ");

print_number(d.value);

uart_send_string(" hPa\r\n");

}

}

}

}

/* ==================== MAIN ==================== */

int main(void) {

init_uart();

init_spi();

init_button();

init_exti();

bme280_init();

sensor_queue = xQueueCreate(5, sizeof(sensor_data_t));

xTaskCreate(sensor_task, "Sensor", 256, NULL, 2, NULL);

xTaskCreate(processor_task, "Print", 256, NULL, 1, NULL);

vTaskStartScheduler();

while (1);

}