STM32VLDISCOVERY+mbed NXP LPC1768+RTOS+KEIL Часть 2

Продолжаем начатое

LPC1768, RTOS, LCD, RTC и Events.
Заводим структуру для хранения данных RTC и переменную:

typedef struct {
    uint32_t RTC_Sec;     /* Second value - [0,59] */
    uint32_t RTC_Min;     /* Minute value - [0,59] */
    uint32_t RTC_Hour;    /* Hour value - [0,23] */
    uint32_t RTC_Mday;    /* Day of the month value - [1,31] */
    uint32_t RTC_Mon;     /* Month value - [1,12] */
    uint32_t RTC_Year;    /* Year value - [0,4095] */
    uint32_t RTC_Wday;    /* Day of week value - [0,6] */
    uint32_t RTC_Yday;    /* Day of year value - [1,365] */
} RTCTime;


RTCTime SetingTime = {0,15,10,26,3,2011};

Определим сообщенияили события которыми будут обмениваться задачи:

#define EVT_RTC_SEC 0x0100
#define EVT_LCD_SEC 0x0010

Из файлика rtc.c: Realtime clock C file for NXP LPC17xx Family Microprocessors надергаем функций:

#define ILR_RTCCIF 0x01
#define ILR_RTCALF 0x02

#define CCR_CLKEN 0x01
#define CCR_CTCRST 0x02
#define CCR_CLKSRC 0x10

void RTCStart( void )
{
   LPC_RTC->CCR |= CCR_CLKEN;
   LPC_RTC->ILR = ILR_RTCCIF;
}

void RTCStop( void )
{  
   LPC_RTC->CCR &= ~CCR_CLKEN;
} 

void RTC_CTCReset( void )
{  
   LPC_RTC->CCR |= CCR_CTCRST;
} 

void RTCSetTime( RTCTime Time )
{
   LPC_RTC->SEC = Time.RTC_Sec;
   LPC_RTC->MIN = Time.RTC_Min;
   LPC_RTC->HOUR = Time.RTC_Hour;
   LPC_RTC->DOM = Time.RTC_Mday;
   LPC_RTC->DOW = Time.RTC_Wday;
   LPC_RTC->DOY = Time.RTC_Yday;
   LPC_RTC->MONTH = Time.RTC_Mon;
   LPC_RTC->YEAR = Time.RTC_Year;   
}

RTCTime RTCGetTime( void )
{
   RTCTime LocalTime;
 
   LocalTime.RTC_Sec = LPC_RTC->SEC;
   LocalTime.RTC_Min = LPC_RTC->MIN;
   LocalTime.RTC_Hour = LPC_RTC->HOUR;
   LocalTime.RTC_Mday = LPC_RTC->DOM;
   LocalTime.RTC_Wday = LPC_RTC->DOW;
   LocalTime.RTC_Yday = LPC_RTC->DOY;
   LocalTime.RTC_Mon = LPC_RTC->MONTH;
   LocalTime.RTC_Year = LPC_RTC->YEAR;
   return ( LocalTime );   
}

void RTC_IRQHandler(void)
{
   LPC_RTC->ILR |= ILR_RTCCIF;
   isr_evt_set (EVT_RTC_SEC, t_PRINTTIME);
}


Функция RTC_IRQHandler(void) посылает сообщение задаче t_PRINTTIME которую позднее создадим.

void RTCInit( void )
{
   LPC_SC->PCONP |= (1 << 9);
   if ( LPC_RTC->RTC_AUX & (0x1<<4) )
   {
      LPC_RTC->RTC_AUX |= (0x1<<4);
   }
   LPC_RTC->AMR = 0;
   LPC_RTC->CIIR = 1; 
   LPC_RTC->CCR = CCR_CLKSRC;
   RTCSetTime(SetingTime);
   LPC_RTC->CCR |= CCR_CLKEN;
   NVIC_EnableIRQ(RTC_IRQn) ;
	
}

С RTC пока все. LCD дальше.

За основу был взят пример от кейловской платы MCB2300. LCD подключен по 4-х битной схеме, напрямую к ногам контроллера, питание от 5 вольт.

Распиновка:
E -> P2.5
RW -> Ground
RS -> P2.4
DATA -> P2.0, P2.1, P2.2, P2.3

Пишем:

void Delay (U32 cnt) 
{  
   while (cnt--);
}

void WriteByte4 (U32 b)
{
   LPC_GPIO2->FIODIR |= 0x3F;       //111111b, направление пинов E,RS,DATA
   LPC_GPIO2->FIOCLR = 0xF;         //1111b, DATA -> 0
   LPC_GPIO2->FIOSET = (b & 0xF);   //выводим
   LPC_GPIO2->FIOSET = 0x20;        //100000b, E -> 1
   Delay (1000);
   LPC_GPIO2->FIOCLR = 0x20;        //100000b, E -> 0
   Delay (1000);
   LPC_GPIO2->FIOSET = 0xF;         //1111b, DATA -> 1
}

void WriteByte (U32 b)
{
   WriteByte4 (b>>4);
   WriteByte4 (b);
}

void WriteCommand (U32 c)
{
   LPC_GPIO2->FIOCLR = 0x10;       //10000b, RS -> 0
   WriteByte (c);
}

void WriteData (U32 d)
{
   LPC_GPIO2->FIOSET = 0x10;      //10000b, RS -> 1
   WriteByte (d);
}

void ClrLCD (void)
{
   WriteCommand (0x01);
}

void InitLCD (void)
{
   Delay(10000000);
   LPC_GPIO2->FIODIR |= 0x3F;     //111111b, направление пинов E,RS,DATA
   LPC_GPIO2->FIOCLR = 0x1F;      //11111b, RS,DATA -> 0
   WriteByte4(0x30);
   Delay(10000000);
   WriteByte4(0x30);
   Delay(10000000);
   WriteByte4(0x30);
   Delay (100000);
   WriteByte4(0x20);
   Delay (100000);
   WriteCommand (0x20);
   Delay (100000);
   WriteCommand (0x28);
   Delay (100000);
   WriteCommand (0x0C);
   Delay (100000);
   WriteCommand (0x06);
   Delay (100000);
   WriteCommand (0x01);
   Delay (100000);
}

void LCDputc (U8 c)
{
   WriteData(c);	
}

void LCDputs (U8 *s)
{
   while (*s) 
   {
      LCDputc (*s++);
   }	
}

LCDgotoxy (U32 x, U32 y) 
{ 
   U32 c;

   c = --x;
   if (--y) 
   {
      c |= 0x40;
   }
   WriteCommand (c | 0x80);  
}


Теперь задача, которая ловит событие от обработчика прерывания RTC и выводит дату и время на LCD и посылает событие мигнуть светодиодом.


__task void f_PRINTTIME (void) 
{
   while (1)   
   {  
      os_evt_wait_or (EVT_RTC_SEC, 0xffff);
      SetingTime = RTCGetTime();	
      sprintf(TimeLCD, "%02d:%02d:%02d", SetingTime.RTC_Hour, SetingTime.RTC_Min, SetingTime.RTC_Sec);
      sprintf(DateLCD, "%02d/%02d/%04d", SetingTime.RTC_Mday, SetingTime.RTC_Mon, SetingTime.RTC_Year);
      LCDgotoxy (4,1);
      LCDputs (DateLCD);
      LCDgotoxy (5,2);
      LCDputs (TimeLCD);
      os_evt_set(EVT_LCD_SEC, t_LED1);
      }	          
    
}


Чтобы заработала sprintf() нужно вначале добавить #include «stdio.h». А еще для задачи f_PRINTTIME (void) мне пришлось задатьперсональный стек:

U64 print_stack[512/8];


Теперь все вместе:

#include "LPC17xx.h"
#include "RTL.h"
#include "stdio.h"

#define EVT_RTC_SEC 0x0100
#define EVT_LCD_SEC 0x0010

U64 print_stack[512/8];

char TimeLCD[10];
char DateLCD[12];

OS_TID t_LED1;
OS_TID t_PRINTTIME;

const unsigned long led_mask[] = { 1UL<<23, 1UL<<21, 1UL<<20, 1UL<< 18 };

typedef struct {
    uint32_t RTC_Sec;     /* Second value - [0,59] */
    uint32_t RTC_Min;     /* Minute value - [0,59] */
    uint32_t RTC_Hour;    /* Hour value - [0,23] */
    uint32_t RTC_Mday;    /* Day of the month value - [1,31] */
    uint32_t RTC_Mon;     /* Month value - [1,12] */
    uint32_t RTC_Year;    /* Year value - [0,4095] */
    uint32_t RTC_Wday;    /* Day of week value - [0,6] */
    uint32_t RTC_Yday;    /* Day of year value - [1,365] */
} RTCTime;


RTCTime SetingTime = {0,15,10,26,3,2011};


#define ILR_RTCCIF 0x01
#define ILR_RTCALF 0x02

#define CCR_CLKEN 0x01
#define CCR_CTCRST 0x02
#define CCR_CLKSRC 0x10


void RTCStart( void )
{
   LPC_RTC->CCR |= CCR_CLKEN;
   LPC_RTC->ILR = ILR_RTCCIF;
}

void RTCStop( void )
{  
   LPC_RTC->CCR &= ~CCR_CLKEN;
} 

void RTC_CTCReset( void )
{  
   LPC_RTC->CCR |= CCR_CTCRST;
} 

void RTCSetTime( RTCTime Time )
{
   LPC_RTC->SEC = Time.RTC_Sec;
   LPC_RTC->MIN = Time.RTC_Min;
   LPC_RTC->HOUR = Time.RTC_Hour;
   LPC_RTC->DOM = Time.RTC_Mday;
   LPC_RTC->DOW = Time.RTC_Wday;
   LPC_RTC->DOY = Time.RTC_Yday;
   LPC_RTC->MONTH = Time.RTC_Mon;
   LPC_RTC->YEAR = Time.RTC_Year;   
}

RTCTime RTCGetTime( void )
{
   RTCTime LocalTime;
 
   LocalTime.RTC_Sec = LPC_RTC->SEC;
   LocalTime.RTC_Min = LPC_RTC->MIN;
   LocalTime.RTC_Hour = LPC_RTC->HOUR;
   LocalTime.RTC_Mday = LPC_RTC->DOM;
   LocalTime.RTC_Wday = LPC_RTC->DOW;
   LocalTime.RTC_Yday = LPC_RTC->DOY;
   LocalTime.RTC_Mon = LPC_RTC->MONTH;
   LocalTime.RTC_Year = LPC_RTC->YEAR;
   return ( LocalTime );   
}

void RTC_IRQHandler(void)
{
   LPC_RTC->ILR |= ILR_RTCCIF;
   isr_evt_set (EVT_RTC_SEC, t_PRINTTIME);
}

void RTCInit( void )
{
   LPC_SC->PCONP |= (1 << 9);
   if ( LPC_RTC->RTC_AUX & (0x1<<4) )
   {
      LPC_RTC->RTC_AUX |= (0x1<<4);
   }
   LPC_RTC->AMR = 0;
   LPC_RTC->CIIR = 1; 
   LPC_RTC->CCR = CCR_CLKSRC;
   RTCSetTime(SetingTime);
   LPC_RTC->CCR |= CCR_CLKEN;
   NVIC_EnableIRQ(RTC_IRQn) ;
	
}

void InitLEDs (void)
{
   LPC_GPIO1->FIODIR = (1<<23) | (1<<21) | (1<<20) | (1<<18);
}

void LEDon (unsigned int num)
{
   LPC_GPIO1->FIOPIN |= led_mask[num];
}

void LEDoff (unsigned int num)
{
   LPC_GPIO1->FIOPIN &= ~led_mask[num];
}

void Delay (U32 cnt) 
{  
   while (cnt--);
}

void WriteByte4 (U32 b)
{
   LPC_GPIO2->FIODIR |= 0x3F;       //111111b, направление пинов E,RS,DATA
   LPC_GPIO2->FIOCLR = 0xF;         //1111b, DATA -> 0
   LPC_GPIO2->FIOSET = (b & 0xF);   //выводим
   LPC_GPIO2->FIOSET = 0x20;        //100000b, E -> 1
   Delay (1000);
   LPC_GPIO2->FIOCLR = 0x20;        //100000b, E -> 0
   Delay (1000);
   LPC_GPIO2->FIOSET = 0xF;         //1111b, DATA -> 1
}

void WriteByte (U32 b)
{
   WriteByte4 (b>>4);
   WriteByte4 (b);
}

void WriteCommand (U32 c)
{
   LPC_GPIO2->FIOCLR = 0x10;       //10000b, RS -> 0
   WriteByte (c);
}

void WriteData (U32 d)
{
   LPC_GPIO2->FIOSET = 0x10;      //10000b, RS -> 1
   WriteByte (d);
}

void ClrLCD (void)
{
   WriteCommand (0x01);
}

void InitLCD (void)
{
   Delay(10000000);
   LPC_GPIO2->FIODIR |= 0x3F;     //111111b, направление пинов E,RS,DATA
   LPC_GPIO2->FIOCLR = 0x1F;      //11111b, RS,DATA -> 0
   WriteByte4(0x30);
   Delay(10000000);
   WriteByte4(0x30);
   Delay(10000000);
   WriteByte4(0x30);
   Delay (100000);
   WriteByte4(0x20);
   Delay (100000);
   WriteCommand (0x20);
   Delay (100000);
   WriteCommand (0x28);
   Delay (100000);
   WriteCommand (0x0C);
   Delay (100000);
   WriteCommand (0x06);
   Delay (100000);
   WriteCommand (0x01);
   Delay (100000);
}

void LCDputc (U8 c)
{
   WriteData(c);	
}

void LCDputs (U8 *s)
{
   while (*s) 
   {
      LCDputc (*s++);
   }	
}

LCDgotoxy (U32 x, U32 y) 
{ 
   U32 c;

   c = --x;
   if (--y) 
   {
      c |= 0x40;
   }
   WriteCommand (c | 0x80);  
}

__task void f_LED1 (void) 
{
   while (1) 
   {
      LEDon (0);
      os_dly_wait (200);
      LEDoff (0);
      os_dly_wait (200);
   }
}


__task void f_PRINTTIME (void) 
{
   while (1)   
   {  
      os_evt_wait_or (EVT_RTC_SEC, 0xffff);
      SetingTime = RTCGetTime();	
      sprintf(TimeLCD, "%02d:%02d:%02d", SetingTime.RTC_Hour, SetingTime.RTC_Min, SetingTime.RTC_Sec);
      sprintf(DateLCD, "%02d/%02d/%04d", SetingTime.RTC_Mday, SetingTime.RTC_Mon, SetingTime.RTC_Year);
      LCDgotoxy (4,1);
      LCDputs (DateLCD);
      LCDgotoxy (5,2);
      LCDputs (TimeLCD);
      os_evt_set(EVT_LCD_SEC, t_LED1);
      }	          
    
}


__task void init (void) 
   {
   os_tsk_prio_self (100);

   t_PRINTTIME = os_tsk_create_user (f_PRINTTIME, 50, &print_stack, sizeof(print_stack));
   t_LED1 = os_tsk_create (f_LED1, 20);
	
   os_tsk_delete_self ();
}

int main (void)
{
SystemInit ();
InitLEDs ();
InitLCD ();
os_sys_init(init);

}


Вроде все, проверьте. Забиваем в RTCTime SetingTime = {0,15,10,26,3,2011}; начальные значения и после прошивки и запуска смотрим как на LCD бегут секунды.

Продолжение позднее…
  • 0
  • 01 апреля 2011, 12:02
  • lexanet

Комментарии (3)

RSS свернуть / развернуть
Вот еще бы знать как под STM32 перегнать…
ЗЫ Хочется плату обвешать и разбираться в процессе.
0
  • avatar
  • qic
  • 23 апреля 2011, 20:16
Дык, тута forum.easyelectronics.ru/viewtopic.php?f=7&t=5088&start=25 выложил работу с LCD под stm32.
0
Только без RTC там, работу с RTC я просто сдернул из исходников STM32_Init.c
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.