STM32 и 7-сегментники (RTOS и RTC).

Давно валялись, все руки не доходили, а счас понадобились, нужны часы и термометр, чтобы значения были видны в темноте и из далека.



#include "stm32f10x.h"
#include "STM32_Init.h"  
#include "rtl.h"
#include "stdio.h"

#define Set_PortC_Pin_8_output ((GPIOC->CRH |= 0x2)|(GPIOC->CRH &= ~0xC))				 
#define Set_PortC_Pin_9_output ((GPIOC->CRH |= 0x20)|(GPIOC->CRH &= ~0xC0))

#define Set_PortB_Pin_10_output ((GPIOB->CRH |= 0x200)|(GPIOB->CRH &= ~0xC00))
#define Set_PortB_Pin_11_output ((GPIOB->CRH |= 0x2000)|(GPIOB->CRH &= ~0xC000))
#define Set_PortB_Pin_12_output ((GPIOB->CRH |= 0x20000)|(GPIOB->CRH &= ~0xC0000))
#define Set_PortB_Pin_13_output ((GPIOB->CRH |= 0x200000)|(GPIOB->CRH &= ~0xC00000))
#define Set_PortB_Pin_14_output ((GPIOB->CRH |= 0x2000000)|(GPIOB->CRH &= ~0xC000000))
#define Set_PortB_Pin_15_output ((GPIOB->CRH |= 0x20000000)|(GPIOB->CRH &= ~0xC0000000))

#define Set_PortA_Pin_0_output ((GPIOA->CRL |= 0x3)|(GPIOA->CRL &= ~0xC))  		
#define Set_PortA_Pin_1_output ((GPIOA->CRL |= 0x30)|(GPIOA->CRL &= ~0xC0))
#define Set_PortA_Pin_2_output ((GPIOA->CRL |= 0x300)|(GPIOA->CRL &= ~0xC00))
#define Set_PortA_Pin_3_output ((GPIOA->CRL |= 0x3000)|(GPIOA->CRL &= ~0xC000))
#define Set_PortA_Pin_4_output ((GPIOA->CRL |= 0x30000)|(GPIOA->CRL &= ~0xC0000))
#define Set_PortA_Pin_5_output ((GPIOA->CRL |= 0x300000)|(GPIOA->CRL &= ~0xC00000))
#define Set_PortA_Pin_6_output ((GPIOA->CRL |= 0x3000000)|(GPIOA->CRL &= ~0xC000000))
#define Set_PortA_Pin_7_output ((GPIOA->CRL |= 0x30000000)|(GPIOA->CRL &= ~0xC0000000))

#define Set_PortA_Pin_8_output ((GPIOA->CRH |= 0x3)|(GPIOA->CRH &= ~0xC))				
#define Set_PortA_Pin_9_output ((GPIOA->CRH |= 0x30)|(GPIOA->CRH &= ~0xC0))
#define Set_PortA_Pin_10_output ((GPIOA->CRH |= 0x300)|(GPIOA->CRH &= ~0xC00))
#define Set_PortA_Pin_11_output ((GPIOA->CRH |= 0x3000)|(GPIOA->CRH &= ~0xC000))

#define EVT_CLOCK_SEC 0x0100

#define SegmentsMask 0x0FF
#define DigitalsMask 0xF00

uint64_t clock_stack[512/8];


struct time  {                        
   char hour;                           /* hour                                */
   char min;                            /* minute                              */
   char sec;                            /* second                              */
};

struct time ctime = { 18,  37,  0 };
char TimeLCD[10];

uint8_t DigitNum = 0;
uint8_t Digit4NUM[5] = { 0, 1, 2, 3 };
uint8_t DigitStrNUM[5];
uint8_t Digits[12] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x80, 0xFF };
uint8_t dot = 0;

const uint32_t led_mask[] = { 1UL<<8, 1UL<<9 };

OS_TID t_LED1;                       
OS_TID t_LED2;
OS_TID t_7SEG;
OS_TID t_CLOCK;

void Delay (uint32_t counter) 
{  
  while (counter--);
}

void RTC_IRQHandler(void)
{
	if (RTC->CRL & (1<<0)) 
	{                       
	RTC->CRL &= ~(1<<0);
	}
	isr_evt_set (EVT_CLOCK_SEC, t_CLOCK);
}

void DevsInit(void) 
{
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
	RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
	RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;

	Set_PortC_Pin_8_output;
	Set_PortC_Pin_9_output;

	Set_PortB_Pin_10_output;
	Set_PortB_Pin_11_output;
	Set_PortB_Pin_12_output;
	Set_PortB_Pin_13_output;
	Set_PortB_Pin_14_output;
	Set_PortB_Pin_15_output;

	Set_PortA_Pin_0_output;
	Set_PortA_Pin_1_output;
	Set_PortA_Pin_2_output;
	Set_PortA_Pin_3_output;
	Set_PortA_Pin_4_output;
	Set_PortA_Pin_5_output;
	Set_PortA_Pin_6_output;
	Set_PortA_Pin_7_output;
	Set_PortA_Pin_8_output;
	Set_PortA_Pin_9_output;
	Set_PortA_Pin_10_output;
	Set_PortA_Pin_11_output;

	GPIOA->BRR = SegmentsMask; 
	GPIOA->BRR = DigitalsMask; 
	Delay (5000000);
	GPIOA->BSRR = SegmentsMask; 
	GPIOA->BSRR = DigitalsMask;          
}

void WriteByte4 (char  b)
{
	GPIOB->BSRR = GPIO_BSRR_BR10;
	GPIOB->BSRR = GPIO_BSRR_BR11;
	GPIOB->BSRR = GPIO_BSRR_BR12;
	GPIOB->BSRR = GPIO_BSRR_BR13;

	GPIOB->BSRR = (b & 0xF)<<10;

	GPIOB->BSRR = GPIO_BSRR_BS14;
	Delay(250);
	GPIOB->BSRR = GPIO_BSRR_BR14;
	Delay(250);

	GPIOB->BSRR = GPIO_BSRR_BS10;
	GPIOB->BSRR = GPIO_BSRR_BS11;
	GPIOB->BSRR = GPIO_BSRR_BS12;
	GPIOB->BSRR = GPIO_BSRR_BS13;
}

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

void WriteCommand (char  c)
{
	GPIOB->BSRR = GPIO_BSRR_BR15;
	WriteByte (c);
}

void WriteData (char d)
{
	GPIOB->BSRR = GPIO_BSRR_BS15;
	WriteByte (d);
}

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

void InitLCD (void)
{
	Delay(1000000);
	GPIOB->BRR = 0xFC00;
	WriteByte4(0x30);
	Delay(20000);
	WriteByte4(0x30);
	Delay(20000);
	WriteByte4(0x30);
	Delay(1000);
	WriteByte4(0x20);
	Delay(1000);
	WriteCommand (0x20);
	Delay(1000);
	WriteCommand (0x28);
	Delay(1000);
	WriteCommand (0x0C);
	Delay(1000);
	WriteCommand (0x06);
	Delay(1000);
	WriteCommand (0x01);
	Delay(1000);
	WriteCommand (0x01);
	Delay(1000);
	WriteCommand (0x01);
	Delay(1000);
	WriteCommand (0x01);
}

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

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

void LCDgotoxy (char x, char y) 
{
  
  char c;

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

void Print7Seg (uint16_t PrintDigit)
{
	uint8_t Digit0[2], Digit1[2], Digit2[2], Digit3[2];

	if (PrintDigit > 9999)
	{
		PrintDigit = 0;
	}
	sprintf(DigitStrNUM, "%04d", PrintDigit);
	strncpy (Digit0, DigitStrNUM, 1);
	strncpy (Digit1, DigitStrNUM+1, 1);
	strncpy (Digit2, DigitStrNUM+2, 1);
	strncpy (Digit3, DigitStrNUM+3, 1);

	Digit4NUM[0] = atoi (Digit0);
	Digit4NUM[1] = atoi (Digit1);
	Digit4NUM[2] = atoi (Digit2);
	Digit4NUM[3] = atoi (Digit3);
}

void LEDOn (uint32_t num) 
{
	GPIOC->BSRR = led_mask[num];
}

void LEDOff (uint32_t num) 
{
	GPIOC->BRR  = led_mask[num]; 
}

__task void f_LED1 (void) 
{
	while (1)
	{
		LEDOn (0);
		os_dly_wait (1000);
		LEDOff (0);
		os_dly_wait (1000);
	}
}

__task void f_LED2 (void) 
{
	while (1)
	{
		LEDOn (1);
		os_dly_wait (2000);
		LEDOff (1);
		os_dly_wait (2000); 
	}
}

__task void f_7SEG (void) 
{
	while (1)
	{
		GPIOA->BSRR = 0xFFF;
		if (DigitNum == 1)
		{
			if (dot == 1)
			{	
				GPIOA->BRR = Digits[Digit4NUM[DigitNum]] | Digits[10] |(1<<(8+DigitNum));	
			}
			if (dot == 0)
			{	
				GPIOA->BRR = Digits[Digit4NUM[DigitNum]] | (1<<(8+DigitNum));
			}
		}
		GPIOA->BRR = Digits[Digit4NUM[DigitNum]] | (1<<(8+DigitNum));
		DigitNum++;
		if (DigitNum == 4)
		{
			DigitNum = 0;	
		}
		os_dly_wait (5); 
	}
}

__task void f_CLOCK (void) 
{	
	uint16_t HourD = 0, MinD = 0;	

	while (1)
	{
		os_evt_wait_or (EVT_CLOCK_SEC, 0xFFFF);
		if (++ctime.sec == 60) 
		{          
			ctime.sec = 0;
			if (++ctime.min == 60) 
			{       
				ctime.min = 0;
				if (++ctime.hour == 24) 
				{    
					ctime.hour = 0;
				}
			}
		}
		HourD = ctime.hour;
		MinD = ctime.min;
		Print7Seg ((HourD * 100 + MinD));
		sprintf(TimeLCD, "%02d:%02d:%02d", ctime.hour, ctime.min, ctime.sec);
		LCDgotoxy (5, 1);
		LCDputs (TimeLCD);
		dot = !(dot);		
	}
}

__task void init (void) 
{
	os_tsk_prio_self (100);
	
	t_7SEG = os_tsk_create (f_7SEG, 99);
	t_LED1 = os_tsk_create (f_LED1, 20);
	t_LED2 = os_tsk_create (f_LED2, 20);
	t_CLOCK = os_tsk_create_user (f_CLOCK, 50, &clock_stack, sizeof(clock_stack));

	os_tsk_delete_self ();
}

int main (void)
{
	SystemInit ();
	stm32_Init();
	DevsInit();
	InitLCD ();
	ClrLCD ();
	LCDgotoxy (1, 1);
	LCDputs ("Starting ...");
	Delay (5000000);
	ClrLCD ();
	os_sys_init(init);
	return 0;
}



Делал на скорую руку, для пробы, без коментов. Если кого что заинтересует, спрашивайте.

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

RSS свернуть / развернуть
На такую задачу можно было микроконтроллер и по проще ))) Не видно термометра, установки времени, будильники, если такой крутой микроконтроллер, можно было мелодии с карточки проигрывать… )))
0
Это только проба, собрано на макетке, никогда сегментники в руках не держал. А проц, другого нет, и будильника не будет, и мелодии тоже :) Термометры рядом, под LCD, тоже первый раз в руках держу, счас начну разбираться. Это будет дочерний модуль, настройка времени будет с основного, через встроенный WEB.
0
Сильно ))) Удачи и терпения )))
0
увидев картинку в начале статьи, моя ленивая задница оторвалась со стула, нашла stm32vldiscovery и шнур и тоже начала изучать их
спасибо!
0
Подскажите, как в этом примере подключен дисплей к плате. (какие пины дисплея — каке пины платы)???
0
Тут получше видно.
RW — на землю,
RS — PB14
E — PB15
D4-D7 — PB10-PB13

Вроде так.
0
Спасибо.
0
ЖК я так понимаю самый обычный 5вольтовый?
0
Да, обычный, запитан от 5 вольт от самой дискавери.
0
а можно схему подключения семисегментника?
0
Схемы не было, все на живую. Примеров подключения в инете как грязи. Различие только в типе транзистора (1 или 0 открываются) и ОА\ОК у 7сегментника. Сегменты через токоограничительные резисторы, общий анод или катод через транзистор. А как к дискавери подключено, видно на фотке.
0
Не вижу у Вас настройки RTC?
0
А про RTOS можно что нибудь написать в комментах хотя бы, а то только для тех, кто в курсе…
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.