Add DMA and LiquidCrystal I2C support

- Implemented DMA functionality with a new dma.c and dma.h file.
- Added LiquidCrystal I2C driver with liquidcrystal_i2c.c and liquidcrystal_i2c.h files.
- Updated CMakeLists.txt to include dma.c and liquidcrystal_i2c.c in the build process.
- Modified build.ninja and compile_commands.json to reflect the new source files.
- Enhanced the main application to utilize the new DMA and LiquidCrystal I2C features.
This commit is contained in:
2025-05-18 16:27:45 +02:00
parent f8c5650c95
commit 344d0000fa
18 changed files with 814 additions and 105 deletions
+58
View File
@@ -0,0 +1,58 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file dma.c
* @brief This file provides code for the configuration
* of all the requested memory to memory DMA transfers.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "dma.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/*----------------------------------------------------------------------------*/
/* Configure DMA */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/**
* Enable DMA controller clock
*/
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel6_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
/* DMA1_Channel7_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
}
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
-6
View File
@@ -78,10 +78,6 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
/* I2C1 clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* I2C1 interrupt Init */
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
@@ -107,8 +103,6 @@ void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle)
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7);
/* I2C1 interrupt Deinit */
HAL_NVIC_DisableIRQ(I2C1_EV_IRQn);
/* USER CODE BEGIN I2C1_MspDeInit 1 */
/* USER CODE END I2C1_MspDeInit 1 */
+296
View File
@@ -0,0 +1,296 @@
#include "liquidcrystal_i2c.h"
extern I2C_HandleTypeDef hi2c1;
uint8_t dpFunction;
uint8_t dpControl;
uint8_t dpMode;
uint8_t dpRows;
uint8_t dpBacklight;
static void SendCommand(uint8_t);
static void SendChar(uint8_t);
static void Send(uint8_t, uint8_t);
static void Write4Bits(uint8_t);
static void ExpanderWrite(uint8_t);
static void PulseEnable(uint8_t);
static void DelayInit(void);
static void DelayUS(uint32_t);
uint8_t special1[8] = {
0b00000,
0b11001,
0b11011,
0b00110,
0b01100,
0b11011,
0b10011,
0b00000
};
uint8_t special2[8] = {
0b11000,
0b11000,
0b00110,
0b01001,
0b01000,
0b01001,
0b00110,
0b00000
};
void HD44780_Init(uint8_t rows)
{
dpRows = rows;
dpBacklight = LCD_BACKLIGHT;
dpFunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
if (dpRows > 1)
{
dpFunction |= LCD_2LINE;
}
else
{
dpFunction |= LCD_5x10DOTS;
}
/* Wait for initialization */
DelayInit();
HAL_Delay(50);
ExpanderWrite(dpBacklight);
HAL_Delay(1000);
/* 4bit Mode */
Write4Bits(0x03 << 4);
DelayUS(4500);
Write4Bits(0x03 << 4);
DelayUS(4500);
Write4Bits(0x03 << 4);
DelayUS(4500);
Write4Bits(0x02 << 4);
DelayUS(100);
/* Display Control */
SendCommand(LCD_FUNCTIONSET | dpFunction);
dpControl = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
HD44780_Display();
HD44780_Clear();
/* Display Mode */
dpMode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
SendCommand(LCD_ENTRYMODESET | dpMode);
DelayUS(4500);
HD44780_CreateSpecialChar(0, special1);
HD44780_CreateSpecialChar(1, special2);
HD44780_Home();
}
void HD44780_Clear()
{
SendCommand(LCD_CLEARDISPLAY);
DelayUS(2000);
}
void HD44780_Home()
{
SendCommand(LCD_RETURNHOME);
DelayUS(2000);
}
void HD44780_SetCursor(uint8_t col, uint8_t row)
{
int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
if (row >= dpRows)
{
row = dpRows-1;
}
SendCommand(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}
void HD44780_NoDisplay()
{
dpControl &= ~LCD_DISPLAYON;
SendCommand(LCD_DISPLAYCONTROL | dpControl);
}
void HD44780_Display()
{
dpControl |= LCD_DISPLAYON;
SendCommand(LCD_DISPLAYCONTROL | dpControl);
}
void HD44780_NoCursor()
{
dpControl &= ~LCD_CURSORON;
SendCommand(LCD_DISPLAYCONTROL | dpControl);
}
void HD44780_Cursor()
{
dpControl |= LCD_CURSORON;
SendCommand(LCD_DISPLAYCONTROL | dpControl);
}
void HD44780_NoBlink()
{
dpControl &= ~LCD_BLINKON;
SendCommand(LCD_DISPLAYCONTROL | dpControl);
}
void HD44780_Blink()
{
dpControl |= LCD_BLINKON;
SendCommand(LCD_DISPLAYCONTROL | dpControl);
}
void HD44780_ScrollDisplayLeft(void)
{
SendCommand(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
}
void HD44780_ScrollDisplayRight(void)
{
SendCommand(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
}
void HD44780_LeftToRight(void)
{
dpMode |= LCD_ENTRYLEFT;
SendCommand(LCD_ENTRYMODESET | dpMode);
}
void HD44780_RightToLeft(void)
{
dpMode &= ~LCD_ENTRYLEFT;
SendCommand(LCD_ENTRYMODESET | dpMode);
}
void HD44780_AutoScroll(void)
{
dpMode |= LCD_ENTRYSHIFTINCREMENT;
SendCommand(LCD_ENTRYMODESET | dpMode);
}
void HD44780_NoAutoScroll(void)
{
dpMode &= ~LCD_ENTRYSHIFTINCREMENT;
SendCommand(LCD_ENTRYMODESET | dpMode);
}
void HD44780_CreateSpecialChar(uint8_t location, uint8_t charmap[])
{
location &= 0x7;
SendCommand(LCD_SETCGRAMADDR | (location << 3));
for (int i=0; i<8; i++)
{
SendChar(charmap[i]);
}
}
void HD44780_PrintSpecialChar(uint8_t index)
{
SendChar(index);
}
void HD44780_LoadCustomCharacter(uint8_t char_num, uint8_t *rows)
{
HD44780_CreateSpecialChar(char_num, rows);
}
void HD44780_PrintStr(const char c[])
{
while(*c) SendChar(*c++);
}
void HD44780_SetBacklight(uint8_t new_val)
{
if(new_val) HD44780_Backlight();
else HD44780_NoBacklight();
}
void HD44780_NoBacklight(void)
{
dpBacklight=LCD_NOBACKLIGHT;
ExpanderWrite(0);
}
void HD44780_Backlight(void)
{
dpBacklight=LCD_BACKLIGHT;
ExpanderWrite(0);
}
static void SendCommand(uint8_t cmd)
{
Send(cmd, 0);
}
static void SendChar(uint8_t ch)
{
Send(ch, RS);
}
static void Send(uint8_t value, uint8_t mode)
{
uint8_t highnib = value & 0xF0;
uint8_t lownib = (value<<4) & 0xF0;
Write4Bits((highnib)|mode);
Write4Bits((lownib)|mode);
}
static void Write4Bits(uint8_t value)
{
ExpanderWrite(value);
PulseEnable(value);
}
static void ExpanderWrite(uint8_t _data)
{
uint8_t data = _data | dpBacklight;
HAL_I2C_Master_Transmit(&hi2c1, DEVICE_ADDR, (uint8_t*)&data, 1, 10);
}
static void PulseEnable(uint8_t _data)
{
ExpanderWrite(_data | ENABLE);
DelayUS(20);
ExpanderWrite(_data & ~ENABLE);
DelayUS(20);
}
static void DelayInit(void)
{
CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk;
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; //~0x00000001;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; //0x00000001;
DWT->CYCCNT = 0;
/* 3 NO OPERATION instructions */
__ASM volatile ("NOP");
__ASM volatile ("NOP");
__ASM volatile ("NOP");
}
static void DelayUS(uint32_t us) {
uint32_t cycles = (SystemCoreClock/1000000L)*us;
uint32_t start = DWT->CYCCNT;
volatile uint32_t cnt;
do
{
cnt = DWT->CYCCNT - start;
} while(cnt < cycles);
}
+120 -9
View File
@@ -19,6 +19,7 @@
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "i2c.h"
#include "spi.h"
#include "usart.h"
@@ -27,6 +28,11 @@
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "pn532_stm32f1.h"
#include "liquidcrystal_i2c.h"
#include <stdlib.h>
#include <time.h>
#include <string.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
@@ -36,7 +42,14 @@
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
typedef struct
{
uint8_t state;
char name[32];
char surname[32];
time_t time;
} incomming_data_t;
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
@@ -59,7 +72,7 @@ void SystemClock_Config(void);
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void sendToServer(uint16_t _uuid);
void send_CalculateCRC(uint8_t *packet);
void parseIncommingPacket(uint8_t *_packet, incomming_data_t *_data);
/* USER CODE END 0 */
/**
@@ -83,7 +96,7 @@ int main(void)
HAL_Init();
/* USER CODE BEGIN Init */
incomming_data_t R_Data;
/* USER CODE END Init */
/* Configure the system clock */
@@ -95,12 +108,21 @@ int main(void)
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_I2C1_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */
printf("Hello!\r\n");
HD44780_Init(2);
HD44780_Clear();
HD44780_SetCursor(0, 0);
HD44780_PrintStr("LightTAM RFID");
HD44780_SetCursor(0, 1);
HD44780_PrintStr("(C) E. Dlabal");
HAL_Delay(2000);
HD44780_Clear();
PN532 pn532;
// PN532_SPI_Init(&pn532);
PN532_I2C_Init(&pn532);
@@ -114,6 +136,8 @@ int main(void)
return -1;
}
PN532_SamConfiguration(&pn532);
HD44780_SetCursor(1, 0);
HD44780_PrintStr("Prilozte kartu");
printf("Waiting for RFID/NFC card...\r\n");
HAL_GPIO_WritePin(GREEN_LED_GPIO_Port, GREEN_LED_Pin, GPIO_PIN_SET);
@@ -127,6 +151,7 @@ int main(void)
/* USER CODE BEGIN 3 */
// Check if a card is available to read
uid_len = PN532_ReadPassiveTarget(&pn532, uid, PN532_MIFARE_ISO14443A, 1000);
if (uid_len == PN532_STATUS_ERROR)
{
@@ -134,9 +159,15 @@ int main(void)
}
else
{
printf("Found card with UID: ");
HD44780_Clear();
HD44780_SetCursor(0, 0);
HD44780_PrintStr("Prosim,ponechte");
HD44780_SetCursor(0, 1);
HD44780_PrintStr("kartu prilozenou");
HAL_GPIO_WritePin(GREEN_LED_GPIO_Port, GREEN_LED_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(ORANGE_LED_GPIO_Port, ORANGE_LED_Pin, GPIO_PIN_SET);
printf("Found card with UID: ");
for (uint8_t i = 0; i < uid_len; i++)
{
printf("%02x ", uid[i]);
@@ -146,8 +177,7 @@ int main(void)
{
printf(" Auth block 6..\r\n");
pn532_error = PN532_MifareClassicAuthenticateBlock(&pn532, uid, uid_len,
6, MIFARE_CMD_AUTH_A, key_a);
pn532_error = PN532_MifareClassicAuthenticateBlock(&pn532, uid, uid_len, 6, MIFARE_CMD_AUTH_A, key_a);
for (uint8_t i = 0; i < 16; i++)
{
@@ -162,20 +192,61 @@ int main(void)
printf("\r\n");
uint32_t value_le = (buff[3] << 24) | (buff[2] << 16) | (buff[1] << 8) | buff[0];
printf("Cislo z bloku (little-endian): %lu\r\n", value_le);
printf("UUID: %lu\r\n", value_le);
sendToServer(value_le);
uint8_t r_packet[76];
HAL_UART_Receive(&huart2, r_packet, 76, HAL_MAX_DELAY);
parseIncommingPacket(r_packet, &R_Data);
HD44780_Clear();
HAL_GPIO_WritePin(ORANGE_LED_GPIO_Port, ORANGE_LED_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GREEN_LED_GPIO_Port, GREEN_LED_Pin, GPIO_PIN_SET);
if (R_Data.state == 1)
{
HAL_GPIO_WritePin(GREEN_LED_GPIO_Port, GREEN_LED_Pin, GPIO_PIN_SET);
HD44780_SetCursor(1, 0);
HD44780_PrintStr("Prichod OK");
HD44780_SetCursor(0, 1);
char name[15];
sprintf(name, "%10s,%1s.", R_Data.surname, R_Data.name);
HD44780_PrintStr(name);
}
else if (R_Data.state == 2)
{
HAL_GPIO_WritePin(GREEN_LED_GPIO_Port, GREEN_LED_Pin, GPIO_PIN_SET);
HD44780_SetCursor(1, 0);
HD44780_PrintStr("Odchod OK");
HD44780_SetCursor(0, 1);
char name[15];
sprintf(name, "%10s,%1s.", R_Data.surname, R_Data.name);
HD44780_PrintStr(name);
}
else if (R_Data.state == 0)
{
HAL_GPIO_WritePin(RED_LED_GPIO_Port, RED_LED_Pin, GPIO_PIN_SET);
HD44780_SetCursor(1, 0);
HD44780_PrintStr("Chyba");
HD44780_SetCursor(0, 1);
HD44780_PrintStr("Zkuste to znovu");
}
while (PN532_ReadPassiveTarget(&pn532, uid, PN532_MIFARE_ISO14443A, 100) != PN532_STATUS_ERROR)
{
HAL_Delay(100);
}
HAL_GPIO_WritePin(RED_LED_GPIO_Port, RED_LED_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GREEN_LED_GPIO_Port, GREEN_LED_Pin, GPIO_PIN_SET);
printf("Card removed. Waiting for next card...\r\n");
break; // Exit the inner while(1) to wait for a new card
HD44780_Clear();
HD44780_SetCursor(1, 0);
HD44780_PrintStr("Prilozte kartu");
if (pn532_error)
{
printf("Error: 0x%02x\r\n", pn532_error);
}
break;
}
}
}
@@ -243,8 +314,48 @@ void sendToServer(uint16_t _uuid)
packet[5] = crc;
HAL_UART_Transmit(&huart2, packet, 6, HAL_MAX_DELAY);
return;
}
void parseIncommingPacket(uint8_t *_packet, incomming_data_t *_data)
{
if (_packet[0] != 0xFF || _packet[1] != 0x55)
{
printf("Invalid packet header\r\n");
return;
}
uint8_t state = _packet[2];
char name[32] = {0};
char surname[32] = {0};
time_t time = 0;
uint8_t crc = 0;
memcpy(name, _packet + 3, 31);
name[31] = '\0';
memcpy(surname, _packet + 35, 31);
surname[31] = '\0';
memcpy(&time, _packet + 67, sizeof(time_t));
for (int i = 0; i < 67 + sizeof(time_t); i++)
{
crc ^= _packet[i];
}
if (crc != _packet[67 + sizeof(time_t)])
{
printf("CRC error\r\n");
return;
}
strcpy(_data->name, name);
strcpy(_data->surname, surname);
_data->state = state;
_data->time = time;
return;
}
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
+23 -8
View File
@@ -55,7 +55,8 @@
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
extern I2C_HandleTypeDef hi2c1;
extern DMA_HandleTypeDef hdma_usart2_rx;
extern DMA_HandleTypeDef hdma_usart2_tx;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
/* USER CODE BEGIN EV */
@@ -201,17 +202,31 @@ void SysTick_Handler(void)
/******************************************************************************/
/**
* @brief This function handles I2C1 event interrupt.
* @brief This function handles DMA1 channel6 global interrupt.
*/
void I2C1_EV_IRQHandler(void)
void DMA1_Channel6_IRQHandler(void)
{
/* USER CODE BEGIN I2C1_EV_IRQn 0 */
/* USER CODE BEGIN DMA1_Channel6_IRQn 0 */
/* USER CODE END I2C1_EV_IRQn 0 */
HAL_I2C_EV_IRQHandler(&hi2c1);
/* USER CODE BEGIN I2C1_EV_IRQn 1 */
/* USER CODE END DMA1_Channel6_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_usart2_rx);
/* USER CODE BEGIN DMA1_Channel6_IRQn 1 */
/* USER CODE END I2C1_EV_IRQn 1 */
/* USER CODE END DMA1_Channel6_IRQn 1 */
}
/**
* @brief This function handles DMA1 channel7 global interrupt.
*/
void DMA1_Channel7_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel7_IRQn 0 */
/* USER CODE END DMA1_Channel7_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_usart2_tx);
/* USER CODE BEGIN DMA1_Channel7_IRQn 1 */
/* USER CODE END DMA1_Channel7_IRQn 1 */
}
/**
+39
View File
@@ -26,6 +26,8 @@
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart2_rx;
DMA_HandleTypeDef hdma_usart2_tx;
/* USART1 init function */
@@ -143,6 +145,39 @@ void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART2 DMA Init */
/* USART2_RX Init */
hdma_usart2_rx.Instance = DMA1_Channel6;
hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart2_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart2_rx);
/* USART2_TX Init */
hdma_usart2_tx.Instance = DMA1_Channel7;
hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart2_tx.Init.Mode = DMA_CIRCULAR;
hdma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_usart2_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart2_tx);
/* USART2 interrupt Init */
HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
@@ -189,6 +224,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
/* USART2 DMA DeInit */
HAL_DMA_DeInit(uartHandle->hdmarx);
HAL_DMA_DeInit(uartHandle->hdmatx);
/* USART2 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART2_IRQn);
/* USER CODE BEGIN USART2_MspDeInit 1 */