Good Stuff Happens in 1:1 Meetings: Why you need them and how to do them well
Led matrix-dokumentáció
1. Mikrokontroller Laboratórium Jegyzőkönyv
1.Feladat leírása:
A12 feladat:
LED mátrix Készítsen kiegészítő hardver egységet az STM32 NUCLEO-F446RE kithez, amely egy 8x8-as
LED mátrix kijelzőt valósít meg!
Az LED mátrix sorkiválasztása történjen időmultiplexelt vezérléssel, az oszlopvezérlés pedig SPI buszon
(sorosan), 8 bites léptetőregiszter segítségével.
Az áramkör megtervezése, megépítése és üzembe helyezése után készítsen el egy az eszköz
bemutatására szolgáló demonstrációs célú tesztprogram rendszert, amely az egyetemünkhöz,
karunkhoz, szakirányunkhoz vagy ágazatunkhoz kapcsolódó animációkat jelenít meg a kijelzőn.
Az animációkat PC-n hozza létre, és az egyes animációk letöltése, kezelése, cseréje soros porton
keresztül, egy kliensprogram segítségével történjen.
A kommunikációhoz virtuális soros portot használjon, melyet a kiten megtalálható USB port
segítségével valósítson meg!
2.Nyáktervezés:
Nyákterv
7. main.c
//időmultiplexelt kirajzoláshoz, forciklussal megyünk végig
ezen a tömbön és mindig 1 sort rajzolunk ki
uint16_t LED_array[]=
{
GPIO_PIN_0,
GPIO_PIN_1,
GPIO_PIN_2,
GPIO_PIN_3,
GPIO_PIN_4,
GPIO_PIN_5,
GPIO_PIN_6,
GPIO_PIN_7
};
//iteratív változóim, itt vannak definiálva mert több 3
szintű egymásba ágyazott forcikulusban is ezeket használom
uint16_t i;
uint16_t j;
uint16_t r;
uint16_t w;
uint8_t temp;//az aktuális sor aktuálisan kirajzolt értéke
benne található(rotálás eredménye ide kerül)
uint8_t SPI_In=0b00000000;
uint8_t SPI_Out;
// tesztváltozó
uint16_t LED_ALL=GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|
GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
//Latch enable és Output enable
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);
// a nucleo zöld ledjét beállítja
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);
//az összes sort GPIO oldalról kikapcsoljuk/negált logika
HAL_GPIO_WritePin(GPIOC,LED_ALL,GPIO_PIN_SET);
//a leddriver shiftreget is inaktiváljuk
SPI_SendReceive(&SPI_In,&SPI_Out,1);
while (1)
{
if(STRING_DISPLAY_ON)
{
for(w=0;w<STRING_LENGTH;w++)
{
init_display(display_aft,mystring[w]);
for(r=0;r<8;r++)
{
shift_aft_to_curr();
for(j=0;j<3;j++)
{
for(i=0;i<8;i++)
{
HAL_GPIO_WritePin(GPIOC,LED_array[i],GPIO_PIN_RESET);
SPI_SendReceive(&display_curr[i],&SPI_Out,1);
HAL_Delay(2);
HAL_GPIO_WritePin(GPIOC,LED_array[i],GPIO_PIN_SET);
}
if(!STRING_DISPLAY_ON)
{goto end;}
}
}
}
}
else
{
for(r=0;r<128;r++)//itt írom ki az uart adatokat
erre külön függvény majd menjen
{
for(j=0;j<HOLD_TIME;j++)//ez a rotálás miatt kell mert minden
r értéket az első forból 3 cilusig kell
kitartani . hal_delay nem jó mert folyamatosan kell pörögni a függvénynek
{
for(i=0;i<8;i++)
{
if(!TIME_IS_ON)
{
switch(CURR_ROW_SIZE)//megnézzük a képernyő üzemmódot és a megfelelő
/ függvényeket meghívva előkésítjük a következő képernyő képet
{
case 8:temp=leddot[i];
break;
case 16:temp=_rotr16(leddot16[i],r);
break;
case 32:temp=_rotr32(leddot32[i],r);
break;
case 64:temp=_rotr64(leddot64[i],r);
break;
}
HAL_GPIO_WritePin(GPIOC,LED_array[i],GPIO_PIN_RESET);//for ciklusba vagyunk minden
i++ ra a következő sor megfelelő ledjei világítanak de a megfelelő időzítéssel
elértem hogy az emberi szemnek folyamatosnak tűnjön a világítás
SPI_SendReceive(&temp,&SPI_Out,1);//a megfelelő sor adatai kimennek
HAL_Delay(2);//kicsit hagyjuk világítani
HAL_GPIO_WritePin(GPIOC,LED_array[i],GPIO_PIN_SET);//majd elsötétítjük
}
A végtelen ciklusomban 3 féle eset alakulhat:
1. szöveg kíírás
2. óra kirajzolás
(1-2 ről bővebben lejjebb)
3. egyéb animáció kirajzolása
ennek 4 módja
o 8 bit: szeszéles képernyőkép,
ekkor nem rotálom a
képernyőt a többi esetben
viszont igen
o 16bit
o 32bit:Az aut animáció ezen
megy
o 64bit
8. else
{
temp=led_hour_array[hour][i]|led_minsec_array[second][i]|led_minsec_array[minute][i];
HAL_GPIO_WritePin(GPIOC,LED_array[i],GPIO_PIN_RESET);//forciklusba vagyunk minden i++
ra a következő sor megfelelő ledjei világítanak de a megfelelő időzítéssel elértem hogy
az emberi szemnek folyamatosnak tűnjön a világítás
SPI_SendReceive(&temp,&SPI_Out,1);//a megfelelő sor adatai kimennek
HAL_Delay(2);//kicsit hagyjuk világítani
HAL_GPIO_WritePin(GPIOC,LED_array[i],GPIO_PIN_SET);//majd elsötétítjük
}
if(STRING_DISPLAY_ON)
{goto end;}
}
}
if(second==0)
{
if(minute==0)
{
if(hour==0)
{
hour=12;
}
hour--;
minute=60;
}
minute--;
second=60;
}
second--;
}
}
end:;
/*}*/
}
/* USER CODE END 3 */
}
TIME Animáció a main.c-ben
Itt minden órához, perchez és másodperchez tartozó 8x8 as kép el van tárolva megfelelő 2D-s tömbökben.
Az órához tartozók a led_hour_array[][] ahogy a perc/másodpercnek is vamn külön tömbje és ezek a megfelelő pillanatokban egymásra
vagyolva vannak. A számolás a ciklus végén történik ez akkor is fut ha nem óra üzemmódban vagyunk.
Szövegkiírás a main.c-ben
Alapvetően 2 tömb van jelen(display_curr[] és display_aft[]) és ezeket a kapott string alapján töltögetjük.
a program indulásakor mind a 2 tömb csupa nulla
amikor először belépünk a szövegkiíró üzemmódba a legfelső forciklus elején az a display_aft[] tömböt az első karakternek
megfelelően inicializáljuk
majd fokozatosan átshiftelem a display_aft[] tartalmát a display_bef[]-be , amikor ez kész újratöltöm a display_aft[]-ot a
következő karakter szerint
amint a szó végére érek aminek a hosszát a STRING_LENGTH változóban tárolom újrakezdem a műveletet
ha új uart parancs érkezik akkor a műveletet goto utasítás segítségével megszakítom
9. gpio.c
void MX_GPIO_Init(void)
{
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);
/*SHF_LE*//*SHF_OE*/
GPIO_InitStruct.Pin =GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|
GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
HAL_GPIO_Init(GPIOC,&GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}
/* USER CODE BEGIN 2 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if((!TIME_IS_ON)&&STRING_DISPLAY_ON)
{
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);//tesztelés
CURR_ROW_SIZE=8;
TIME_IS_ON=1;
HOLD_TIME=40;
STRING_DISPLAY_ON=0;
return;
}
if(TIME_IS_ON&&(!STRING_DISPLAY_ON))
{
STRING_DISPLAY_ON=0;
TIME_IS_ON=0;
CURR_ROW_SIZE=32;
HOLD_TIME=3;
return;
}
if((!TIME_IS_ON)&&(!STRING_DISPLAY_ON))
{
STRING_DISPLAY_ON=1;
TIME_IS_ON=0;
return;
}
}
spi.c
const uint32_t spi_timeout = 5000;
/* USER CODE END 0 */
SPI_HandleTypeDef hspi3;
/* SPI3 init function */
void MX_SPI3_Init(void)
{
hspi3.Instance = SPI3;
hspi3.Init.Mode = SPI_MODE_MASTER;
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi3.Init.NSS = SPI_NSS_SOFT;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
Itt érdemes megemlíteni hogy a PC13-on
lévő pushbutton külső megszakítás hajt
végre, a PC-ről lehúzott eszközön ennek
segítségévekl tudok az animációk között
váltani.
A gomb megnyomására a soron következő
üzemmód fontos változói beálításra
kerülnek, ezek funkcióját deklarációjuknál
kifejtem.
spi.c ben az spi-hez tartozó az alapvető
funkciók lettek megvalósítva.
küldés,fogadás,inicializálás,stb.
10. hspi3.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi3) != HAL_OK)
{
Error_Handler();
}
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(spiHandle->Instance==SPI3)
{
/* USER CODE BEGIN SPI3_MspInit 0 */
/* USER CODE END SPI3_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_SPI3_CLK_ENABLE();
/**SPI3 GPIO Configuration
PC10 ------> SPI3_SCK
PC11 ------> SPI3_MISO
PC12 ------> SPI3_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* USER CODE BEGIN SPI3_MspInit 1 */
/* USER CODE END SPI3_MspInit 1 */
}
}
void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{
if(spiHandle->Instance==SPI3)
{
/* USER CODE BEGIN SPI3_MspDeInit 0 */
/* USER CODE END SPI3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_SPI3_CLK_DISABLE();
/**SPI3 GPIO Configuration
PC10 ------> SPI3_SCK
PC11 ------> SPI3_MISO
PC12 ------> SPI3_MOSI
*/
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12);
}
/* USER CODE BEGIN SPI3_MspDeInit 1 */
/* USER CODE END SPI3_MspDeInit 1 */
}
/* USER CODE BEGIN 1 */
HAL_StatusTypeDef SPI_Send(uint8_t* pData, uint16_t dataSize)
{
HAL_SPI_Transmit(&hspi3,pData,dataSize,spi_timeout);
return HAL_OK;
}
HAL_StatusTypeDef SPI_Receive(uint8_t* pData, uint16_t dataSize)
{
HAL_SPI_Receive(&hspi3,pData,dataSize,spi_timeout);
return HAL_OK;
}
/** SPI küldés és fogadás egyszerre. */
HAL_StatusTypeDef SPI_SendReceive(uint8_t* pDataIn, uint8_t *pDataOut, uint16_t dataSize)
{
HAL_SPI_TransmitReceive(&hspi3,pDataIn,pDataOut,dataSize,spi_timeout);
return HAL_OK;
}
usart.c
#include "usart.h"
#include "gpio.h"
#include "string.h"
#include "time.h"
#include "font.h"
11. /* USER CODE BEGIN 0 */
uint8_t lastReceivedUartCommand = 0;
char rxBuffer;
uint16_t CURR_ROW_SIZE=32;//alapértelmezetten 32-nek lett most véletlen beállítva
de üres regisztert rotál tehát lényegtelen, az első beérkezett uart
csomagnál eldől hogy milyen üzemmódban működünk
#define TXBUFFERSIZE 255
char txBuffer[TXBUFFERSIZE];
HAL_StatusTypeDef stat;
uint8_t mystring[50]={'n'-' ','i'-' ','n'-' ','c'-' ','s'-' ',' '-' ','s'-' ','z'-' ','o'-' ','v'-' ','e'-' ','g'-' ',' '-' '};
//ebbe tárolom a kiírandó szót
uint8_t STRING_LENGTH_INIT;//bekérem a sring hosszát
uint8_t STRING_LENGTH=13;//string hossza
uint8_t STRING_LENGTH_TEMP=0;//ennek segítségével nézem hogy elértem már e a kért szó végét
uint8_t STRING_DISPLAY_ON=0;//magának a string kiírásnak az állapotjelzője
uint8_t STRING_IS_ON=0;//stringkiírással kapcsolatos adatok uarton való fogadásának állapota
uint8_t TIME_IS_ON=1; //az óra üzemmódot jelző változó
uint8_t TIME_INIT=0; //ez a változó azt jelzi amikor az óra inicializálás adatai jönnek, amíg ez igaz minden adatot erre hasznosítunk
uint8_t HOLD_TIME=50;//meddig tatson egy képernőképet a kimeneten ,,, time nál ugy 1 mp ig kell
uint8_t time_type=0;
uint8_t digit=1;
uint8_t leddot[]=//itt tárolom a bejövő adatot externnel hivatkozok rá a mainből
{
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
uint16_t leddot16[]=//itt tárolom a bejövő adatot externnel hivatkozok rá a mainből
{
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000
};
uint32_t leddot32[]=//itt tárolom a bejövő adatot externnel hivatkozok rá a mainből
{
0x00ff00ff,
0x38c738c7,
0x7c8344bb,
0x7c8344bb,
0x7c8344bb,
0x38c738c7,
0x00ff00ff,
0x00ff00ff
};
uint64_t leddot64[]=//itt tárolom a bejövő adatot externnel hivatkozok rá a mainből
{
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000
};
uint8_t display_curr[]=
{
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
uint8_t display_aft[]=
{
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
uint16_t Row_counter=0;//maximumértéke a vízszintes szélességet befojásolja
alapértelmezetten 8 de ha rotáljuk shiftreget akkor lehet jóval több is
uint16_t Col_counter=0;//függöleges szélesség, maximum ugye 8 lehet ,
persze lehet bonyolítani itt is a dolgot
//az ascii karaktert a megfelelő üzemmódokban a
megfelelő típussá kell konvertálni ezekre ott van szülségem
uint8_t intBuffer8;
uint16_t intBuffer16;
uint32_t intBuffer32;
display_curr[] és display_aft[] inicializálás
működésük előbbikben részletezve volt
12. uint64_t intBuffer64;
uint8_t second=59;
uint8_t minute=59;
uint8_t hour=11;
//void init_display();
//A uart callback függványből ezek a függvények hívódnak meg a megfelelő időpontban
void UART_PROCESS_8BITDISPLAY();
void UART_PROCESS_16BITDISPLAY();
void UART_PROCESS_32BITDISPLAY();
void UART_PROCESS_64BITDISPLAY();
void UART_ASCII_SHIFT_CONVERT();
void ROW_COL_STEP();
/* USER CODE END 0 */
UART_HandleTypeDef huart2;
/* USART2 init function */
void MX_USART2_UART_Init(void)
{
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
stat=HAL_UART_Receive_IT(&huart2, (uint8_t*)&rxBuffer, 1);
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(uartHandle->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspInit 0 */
/* USER CODE END USART2_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_USART2_CLK_ENABLE();
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
/* USER CODE BEGIN USART2_MspInit 1 */
/* USER CODE END USART2_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspDeInit 0 */
/* USER CODE END USART2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART2_CLK_DISABLE();
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
/* Peripheral interrupt Deinit*/
HAL_NVIC_DisableIRQ(USART2_IRQn);
}
/* USER CODE BEGIN USART2_MspDeInit 1 */
/* USER CODE END USART2_MspDeInit 1 */
}
/* USER CODE BEGIN 1 */
/** String küldése, nem blokkolva. */
HAL_StatusTypeDef UART_SendString(char *str)
{
//IDE INKÁBB VÁRAKOZÓSI SOR KELL
while ((huart2.gState != HAL_UART_STATE_BUSY_RX) && (huart2.gState != HAL_UART_STATE_READY))
{
}
strncpy(txBuffer, str, TXBUFFERSIZE);
uint32_t length = strlen(txBuffer);
return HAL_UART_Transmit_IT(&huart2, (uint8_t*)txBuffer, length);
return HAL_OK;
óra,perc,másodperc 0-tól 59-ig megy sikerült
fordított sorrendbe bepötyögnöm az összeset
úgyhogy azért számlálok visszafele.
13. }
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *handle)
{
uint8_t len_temp;
if(STRING_IS_ON)
{
if(STRING_LENGTH_INIT)
{
len_temp=rxBuffer-'0';
STRING_LENGTH=len_temp+10*STRING_LENGTH;
STRING_LENGTH_INIT--;
STRING_LENGTH_TEMP=0;
}
else
{
mystring[STRING_LENGTH_TEMP]=rxBuffer-'!'+1;
STRING_LENGTH_TEMP++;
if(STRING_LENGTH_TEMP==STRING_LENGTH)
{
STRING_IS_ON=0;
STRING_DISPLAY_ON=1;
}
}
}
else
{
if(TIME_INIT)
{
switch(rxBuffer)// üzemmódnak megfelelő uartkezelés hívódik
{
case 'h':
time_type=0;
digit=1;
break;
case 'm':
time_type=1;
digit=1;
break;
case 's':
time_type=2;
digit=1;
break;
default:
switch(time_type)
{
case 0:hour=rxBuffer;
break;
case 1:minute=rxBuffer;
break;
case 2:second=rxBuffer;
TIME_INIT=0;
break;
}
}
}
else
{
switch(rxBuffer)//az egyik legfontosabb rész , itt döntjük
el hogy a bejövőcsomag az üzemmódot akarja állítani vagy pedig a kijelzőt
{ //kijelzőt csak 0 és 1 gyel állítunk ,
kliensprogramra erre figyelek ezért van itt a default , ha üzemmód
csomag érkezik azt nem tároljuk el a leddot[]tömben hanem csak értelmezzük
case'a':CURR_ROW_SIZE=8;//8 bites animáció nincs shift
TIME_IS_ON=0;
HOLD_TIME=3;
STRING_DISPLAY_ON=0;
break;
case'b':CURR_ROW_SIZE=16;//16 bites animáció
TIME_IS_ON=0;
HOLD_TIME=3;
STRING_DISPLAY_ON=0;
break;
case'c':CURR_ROW_SIZE=32//32 bites animáció
TIME_IS_ON=0;
HOLD_TIME=3;
STRING_DISPLAY_ON=0;
break;
case'd':CURR_ROW_SIZE=64;// 64 bites animáció
TIME_IS_ON=0;
HOLD_TIME=3;
STRING_DISPLAY_ON=0;
break;
case't':CURR_ROW_SIZE=8;//idő animáció
TIME_IS_ON=1;
TIME_INIT=1;
ACTUAL_TIME_INIT=1;
HOLD_TIME=40;
STRING_DISPLAY_ON=0;
break;
case's':STRING_IS_ON=1; //szöveg kiírás
STRING_LENGTH_INIT=2;
STRING_LENGTH=0;
TIME_IS_ON=0;
break;
default:
switch(CURR_ROW_SIZE)// üzemmódnak megfelelő uartkezelés hívódik
{
case 8:UART_PROCESS_8BITDISPLAY();
break;
case 16:UART_PROCESS_16BITDISPLAY();
break;
case 32:UART_PROCESS_32BITDISPLAY();
break;
Itt történik a string valamint annak hosszának a
beolvasása. A hossz 2 karakter ennek
lekezelése látható az if igaz ágában.
Amint beolvastunk mindent a string
inicializálás állapotának jelzőbitjét kinullázzuk
majd a string kiírás jelzőbitjét igazzá teszem.
Óra üzemmódban az aktuális idő
beolvasása.Minden időegység 1 karakter
hosszú, kliens oldalon itt charrá konvertálok és
utána használom csak a .Tostring() függvényt
hogy elférjek 1 byte-on.
amikor semmilyen inicializálás
nem zajlik itt dől el hogy melyik
üzemmódba lépünk.
érdemes megemlíteni hogy a
Holdtime alapvetően 3 hogy
megfelelően sebességgel
heledjon a tartalom a kijelzőn,
óra üzemmódban viszont kb.
egy másodpercenként váltson
ezért 40.
14. case 64:UART_PROCESS_64BITDISPLAY();
break;
}
break;
}
}
}
HAL_UART_Receive_IT(handle, (uint8_t*)&rxBuffer, 1);
}
void UART_PROCESS_8BITDISPLAY()
{
uint8_t i;
if((Row_counter==0)&&(Col_counter==0))//mindig akkor nullázzuk a képernyőt amikor a
következő képernyőkép első bitje megérkezett(értelemszerűen) és azt egyből ki is rajzoljuk
{
for(i=0;i<8;i++)
{
leddot[i]=0;
}
//draw_OK=0;
}
UART_ASCII_SHIFT_CONVERT();//beérkezett asciiból kivonjuk a '0'
karaktert majd a megfelelő típusra konvertáljuk ezelután annyival shifteljük ahanyadik adat a sorban
leddot[Col_counter]=leddot[Col_counter]| intBuffer8;//az eddigi adatokhoz hozzávagyolom
Row_counter++;
ROW_COL_STEP();//a sorok és oszlopok novelésének nullázásának lekezelése
}
void UART_PROCESS_16BITDISPLAY()
{
uint8_t i;
if((Row_counter==0)&&(Col_counter==0))
{
for(i=0;i<8;i++)
{
leddot16[i]=0;
}
//draw_OK=0;
}
UART_ASCII_SHIFT_CONVERT();
leddot16[Col_counter]=leddot16[Col_counter]| intBuffer16;//az eddigi adatokhoz hozzávagyolom
Row_counter++;
ROW_COL_STEP();
}
void UART_PROCESS_32BITDISPLAY()
{
uint8_t i;
if((Row_counter==0)&&(Col_counter==0))
{
for(i=0;i<8;i++)
{
leddot32[i]=0;
}
//draw_OK=0;
}
UART_ASCII_SHIFT_CONVERT();
leddot32[Col_counter]=leddot32[Col_counter]| intBuffer32;//az eddigi adatokhoz hozzávagyolom
Row_counter++;
ROW_COL_STEP();
}
void UART_PROCESS_64BITDISPLAY()
{
uint8_t i;
if((Row_counter==0)&&(Col_counter==0))
{
for(i=0;i<8;i++)
{
leddot64[i]=0;
}
//draw_OK=0;
}
UART_ASCII_SHIFT_CONVERT();
leddot64[Col_counter]=leddot64[Col_counter]| intBuffer64;//az eddigi adatokhoz hozzávagyolom
Row_counter++;
ROW_COL_STEP();
}
void UART_ASCII_SHIFT_CONVERT()
{
rxBuffer = rxBuffer - '0';//1 vagy 0 érkezik és char ból int be konvertálom
switch(CURR_ROW_SIZE)
{
case 8:intBuffer8=rxBuffer;
intBuffer8=intBuffer8<<Row_counter;
break; //annyit shiftelem amelyik sorba tartozik az adat
case 16:intBuffer16=rxBuffer;
intBuffer16=intBuffer16<<Row_counter;
break;
case 32:intBuffer32=rxBuffer;
intBuffer32=intBuffer32<<Row_counter;
egyenként érkeznek be az
animáció bitjei ezeket
mikor beérkeznek a
képernyő egy sorának
méretére konvertálom
majd annyival shiftelem
ahanyadik elemnél tartunk
az adott „col” ban és ezt
végül hozzávagyolom az
eddigi értékhez
15. break;
case 64:intBuffer64=rxBuffer;
intBuffer64=intBuffer64<<Row_counter;
break;
}
}
void ROW_COL_STEP()
{
//azér van itt nyolc mert mindig kiírás után novelem a sort
azaz ha a 7. row-t kiírtam akkor növelek 8 ra és ilyenkor 0-zódik minden
//a következő kiírés pedig már az új kijelzőkép első pontja lesz
if(Row_counter%CURR_ROW_SIZE==0)//ha elértem a sor végét az
{ //oszlopot növelem a sort nullázom
if(Col_counter==7)//ha bejött minden adat akkor 0-zok mindent
{//utsó bit nem megy ki ezt még javítani kell
Row_counter=0;
Col_counter=0;
//draw_OK=1;
//init_display();
}
else
{
Col_counter++;
Row_counter=0;
}
}
}
void USART3_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart2);
}
void init_display(uint8_t* display,uint8_t letternum)
{
uint8_t i;
uint8_t temp;
for(i=0;i<8;i++)
{
temp=IMAGES[letternum][i];
temp = (temp & 0xF0) >> 4 | (temp & 0x0F) << 4;
temp = (temp & 0xCC) >> 2 | (temp & 0x33) << 2;
temp = (temp & 0xAA) >> 1 | (temp & 0x55) << 1;
display[i]=temp;
}
}
font.h
http://xantorohara.github.io/led-matrix-editor/#
led_time.h
tartalmaza az egyes időpontokhoz tartozó képet
Kliensoldal:
itt döntöm el hogy új sorba
kell e lépni esetleg végeztem
a beolvasással
16. using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace MIKROLAB
{
public partial class Form1 : Form
{
private SerialPort MyPort;
private char actualstatus;
private int CURR_DISPLAY_SIZE;
string LETTER_A ="0001100000111100001111000110011001100110111111111111111111000011";
string LETTER_B= "1111110011000110110000111111111011111110110000111100011011111100";
string LETTER_C ="0011111101111111111000001110000011100000111000000111111100111111";
string LETTER_CC =
"001111110011111101111111011111111110000011100000111000001110000011100000111000001110000011100
00001111111011111110011111100111111";
string LETTER_AAAA =
"000110000001100000011000000110000001100000011000000110000001100000111100001111000011110000111
18. {
MyPort.Write(LETTER_AAAA[i].ToString());
}
}
private void button5_Click(object sender, EventArgs e)
{
MyPort.Write("b");
for (int i = 0; i < 128; i++)
{
MyPort.Write(TWO_SMILE[i].ToString());
}
}
private void button2_Click(object sender, EventArgs e)
{
MyPort.Write("a");
for (int i = 0; i < 64; i++)
{
MyPort.Write("0");
}
}
private void button6_Click_1(object sender, EventArgs e)
{
int hour = DateTime.Now.Hour;
if (hour > 11)
{
hour = hour - 13;
}
//hour = 12 - hour;
int minute = 60- DateTime.Now.Minute;
int second = 60- DateTime.Now.Second;
MyPort.Write("t");
MyPort.Write("h");
MyPort.Write(((char)hour).ToString());
MyPort.Write("m");
MyPort.Write(((char)minute).ToString());
MyPort.Write("s");
MyPort.Write(((char)second).ToString());
}
private void button7_Click(object sender, EventArgs e)
{
MyPort.Write("s");
if (textBox1.TextLength < 10)
{
MyPort.Write("0");
}
MyPort.Write(textBox1.TextLength.ToString());
MyPort.Write(textBox1.Text);
}
}
}
Óra inicializálás.
24h –s formátumot 12h-ssá
kell varázsolni
A szöveg valamint annak
hosszának elküldése
ezzel a függvénnyel
„kapcsolom ki” a
képernyőt
19. ha az eszközre ráadjuk az áramot esz
a képernyő fogad
a hátulsó nyomógombbal váltogathatjuk
az üzemmódokat, amikor még nem
dugtuk föl pc-re a default értékeket
láthatjuk
szöveg kiírásnál a „nincs szöveg” string
shiftelődik
20. A kliensszoftverrel a következő funkciók érhetőek el.
1. Aut-BME animáció 32x8 –as képernyőn
2. Smile animáció 8x8 as képernyőn nincs shift
3. smile animáció 16x8 as képernyőn van shift
21. 4. szöveg kiírása maximum 50 karakterig
5. képernyő lekapcsolása
6. Aktuális idő mutatása