[PROJEKT] KA-NUCLEO-F411CE i Waveshare Accessory Shield – obsługa diody RGB i sterownika P9813
Programowanie funkcji obsługi sterownika
Włączenie zasilania diody LED RGB
Pierwszym etapem prac nad oprogramowaniem będzie ustawienie stanu wysokiego wyjścia oznaczonego jako ON_Pin (PA6). Spowoduje to włączenie zasilania +5 V, które zasili diodę LED. W tym celu dodajemy instrukcję:
HAL_GPIO_WritePin(ON_GPIO_Port, ON_Pin, GPIO_PIN_SET);
Wprowadzamy ją w bloku:
/* USER CODE BEGIN 2 */ /* USER CODE END 2 */
Blok ten znajduje się w funkcji main przed pętlą nieskończoną while.
Modyfikacja częstotliwości występowania przerwania SysTick
Aby mieć możliwość generowania sygnału zegarowego o okresie 70 us, musimy wprowadzić modyfikację występowania przerwania timera systemowego SysTick. Dokonujemy tego dopisując funkcję konfiguracyjną w postaci:
void SysTick_Init(void)
{
/****************************************
*SystemFrequency/1000 1ms *
*SystemFrequency/100000 10us *
*SystemFrequency/1000000 1us *
*****************************************/
while (SysTick_Config(SystemCoreClock / 1000000) != 0)
{
} // One SysTick interrupt now equals 1us
}
Dodajemy ją w bloku:
/* USER CODE BEGIN 4 */ /* USER CODE END 4 */
Dodatkowo powinniśmy dodać jej prototyp w sekcji:
/* USER CODE BEGIN PFP */ /* Private function prototypes -----------------------------------------------*/ void SysTick_Init(void); /* USER CODE END PFP */
W tej sekcji będziemy dodawali również prototypy do kolejnych pisanych przez nas funkcji.
Aby wszystko działało poprawnie, wywołujemy funkcję przed pętlą główną funkcji main:
/* USER CODE BEGIN 2 */ SysTick_Init(); HAL_GPIO_WritePin(GPIOA, ON_Pin, GPIO_PIN_SET); /* USER CODE END 2 */
Generowanie sygnału zegarowego dla sterownika P9813
Zgodnie z interfejsem opisanym w dokumentacji sterownika, jak i wcześniejszymi założeniami, wygenerujemy sygnał prostokątny będący sygnałem zegarowym. Zostanie on wygenerowany na pinie oznaczonym przez nas jako CIN (PB4). W tym celu zdefiniujemy funkcję DelayClockTime. Jej argumentem jest czas w mikrosekundach. Aby czas oczekiwania wynosił dokładnie 35 us, należy od podanego czasu odjąć 3 us. Następnie program przechodzi do pętli while, w której pozostaje do momentu kiedy zmienna delayUsCounter osiągnie zadaną wartość.
void DelayClockTime(int _TIME_TO_DELAY)
{
delayUsCounter = 0;
if(_TIME_TO_DELAY > 3)
{
_TIME_TO_DELAY -= 3;
}
while(delayUsCounter < _TIME_TO_DELAY)
{
//Wait for correct value of delayUsCounter.
}
}
Zmienna delayUsCounter została zdefiniowana na samym początku pliku stm32f4xx_it.c w bloku:
/* USER CODE BEGIN 0 */ uint8_t delayUsCounter = 0; /* USER CODE END 0 */
oraz w pliku main.c:
/* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ extern uint8_t delayUsCounter; /* USER CODE END PV */
Parametr extern oznacza, że zmienna została zdefiniowana w innym pliku, ale definicja umożliwia korzystanie z niej w pliku main.c.
Inkrementacja wartości zmiennej odbywa się w funkcji przerwania SysTick:
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
delayUsCounter++;
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
HAL_SYSTICK_IRQHandler();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
Aby wygodnie generować sygnał zegarowy, zdefiniowana została funkcja P9813_CLK():
void P9813_CLK()
{
HAL_GPIO_WritePin(GPIOB, CIN_Pin, GPIO_PIN_SET);
DelayClockTime(35);
HAL_GPIO_WritePin(GPIOB, CIN_Pin, GPIO_PIN_RESET);
DelayClockTime(35);
}
Umożliwia ona generowanie jednego okresu sygnału prostokątnego o czasie trwania 70 us.
Wysyłanie bajtu danych do sterownika P9813
Kolejną funkcją, którą zdefiniujemy i która jest niezbędna do pracy z układem P9813, jest funkcja przesyłająca jeden bajt danych. Będzie ona korzystać z wcześniej zdefiniowanej funkcji P9813_CLK(). Jej kod przedstawia się następująco:
void P9813_SendByte(uint8_t _BYTE_TO_SEND)
{
int i = 0;
for(i = 0; i < 8; i++)
{
if((_BYTE_TO_SEND & 0x80) != 0)
{
HAL_GPIO_WritePin(GPIOB, DIN_Pin, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOB, DIN_Pin, GPIO_PIN_RESET);
}
P9813_CLK();
_BYTE_TO_SEND <<= 1;
}
}
Jej argumentem jest bajt, który zostanie wysłany do układu sterownika. Cała procedura ma za zadanie ustawić stan na wyjściu opisanym jako DIN, a następnie wygenerować pełen okres sygnału zegarowego dla sterownika P9813. Dane przesyłane są w kolejności od najstarszego do najmłodszego bitu. W tym celu została wykorzystana pętla for, która wykona się 8 razy (8 bitów w bajcie). Na początku pętli, wykonywana jest instrukcja sprawdzająca najstarszy bit zmiennej _BYTE_TO_SEND, a następnie w zależności od tego czy jest to 1 czy 0, ustawiany jest stan wysoki na wyjściu DIN. Po każdorazowym ustawieniu bitu następuje wykonanie funkcji P9813_CLK(). Jako ostatnia instrukcja w pętli wykonywana jest operacja przesunięcia bitowego z nadpisaniem o jeden bit w lewo. Dzięki takiemu zabiegowi sprawdzanie kolejnych bitów odbywa się za pomocą jednej i tej samej maski 0x80 (0b10000000).
Wysyłanie prefiksu do sterownika P9813
Zgodnie z protokołem komunikacyjnym, konieczne jest wysłanie do sterownika prefiksu będącego pierwszą częścią ramki danych. W tym celu została utworzona funkcja P9813_SendPrefix. Została ona przeciążona trzema argumentami o kolorze, jaki zostaje wysłany do sterownika diody LED RGB.
void P9813_SendPrefix(uint8_t _RED, uint8_t _GREEN, uint8_t _BLUE)
{
uint8_t prefixToSend = 0;
prefixToSend = 0xC0;
if((_BLUE & 0x80) == 0) prefixToSend |= 0x20;
if((_BLUE & 0x40) == 0) prefixToSend |= 0x10;
if((_GREEN & 0x80) == 0) prefixToSend |= 0x8;
if((_GREEN & 0x40) == 0) prefixToSend |= 0x4;
if((_RED & 0x80) == 0) prefixToSend |= 0x2;
if((_RED & 0x40) == 0) prefixToSend |= 0x1;
P9813_SendByte(prefixToSend);
}
Zmienna wewnętrzna o nazwie prefixToSend zawiera kompletny prefix gotowy do wysłania. Na początku zmienna ta jest zerowana oraz zostają w niej zapisane dwa najstarsze bity o wartości „1” – 0xC0 (0b11000000). Następnie sprawdzane są dwa najstarsze bity każdego z podanych kolorów i ich negacja jest zapisana do zmiennej. Kolory zapisywane są w notacji BGR, zgodnie z opisanym w dokumentacji protokołem. Na końcu tak przygotowany prefix wysyłany jest do układu za pomocą wcześniej przygotowanej funkcji do przesyłania bajtu danych.
Wysyłanie ramki danych o kolorze do sterownika P9813
Ostatnia zdefiniowana funkcja przesyła kompletną ramkę danych do sterownika P9813 i umożliwia wyświetlenie danego koloru na diodzie LED RGB.
void P9813_SetColor(uint8_t _RED, uint8_t _GREEN, uint8_t _BLUE)
{
P9813_SendByte(0x00);
P9813_SendByte(0x00);
P9813_SendByte(0x00);
P9813_SendByte(0x00);
P9813_SendPrefix(_RED, _GREEN, _BLUE);
P9813_SendByte(_BLUE);
P9813_SendByte(_GREEN);
P9813_SendByte(_RED);
}
Zgodnie z protokołem wysyłane są 32 bity o wartości „0” oznaczające początek transmisji, następnie wysyłany jest prefix, a po nim trzy bajty opisujące natężenie koloru o wartości od 0…255 dla każdej z diod. Kolory również są wysyłane w notacji BGR.

Technologie End of Life i bezpieczeństwo sieci – wyzwania Europy związane z tzw. długiem technologicznym
Najczęstsze błędy firm przy wyborze dostawcy energii i jak ich uniknąć
Fotorezystor, czyli czujnik światła dwojakiego działania. Przykład innowacji w automatyce i elektronice możliwej dzięki technologii fotooporników 



