I'm trying to start a simple communication with nokia 5110 LCD using SPI protocol. I'm using SPI2 peripheral on stm32f103c8t6 board but it doesn't work as intended.
The code should intialize SPI preipheral and send two commands to the LCD : first command to use the basic instruction mode and the second to set all segments on.
Here's my code :
#include "stm32f10x.h" // Device header
#define NRES GPIOA->ODR |= ((((uint16_t) 0x1) << 8))
#define RES GPIOA->ODR &= (~(((uint16_t) 0x1) << 8))
#define SET_DK GPIOA->ODR |= ((((uint16_t) 0x1) << 9))
#define RESET_DK GPIOA->ODR &= (~(((uint16_t) 0x1) << 9))
void CLK_init (void);
void RCC_init (void);
void GPIO_init(void);
void SPI_init (void);
void LCD_init (void);
void delay(void);
int main(void)
{
char volatile a ;
uint32_t tmp = GPIOB->CRH;
CLK_init ();
RCC_init ();
GPIO_init();
SPI_init ();
LCD_init ();
RESET_DK;
SPI2->DR = (0x20); //LCD COMMAND : BASIC SET , HORIZ ADDRESSING
a = SPI2->SR & (((uint16_t)0x1)<<1); //TXE BIT
while(a != 0x2) //WAIT UNTIL TX BUFFER IS EMPTY
{}
SPI2->DR = (0x9); //E=1 , D= 0 - ALL SEGMENTS ON
while(1)
{
SPI2->DR = (0x9); //E=1 , D= 0 - ALL SEGMENTS ON
while(a != 0x2) //WAIT UNTIL TX BUFFER IS EMPTY
{}
}
}
void CLK_init(void)
{
// 01: HSE oscillator used as system clock
RCC -> CFGR |= (uint32_t)0x1;
RCC -> CFGR &= ~((uint32_t)0x1) << 1;
RCC -> CFGR &= ~(((uint32_t)0x7) << 11);
RCC -> CFGR |= ((uint32_t)0x1) << 13;
}
void RCC_init(void)
{
RCC->APB2ENR |= ((uint32_t)0x1)<<0; //Enable AFIO pin
RCC->APB2ENR |= ((uint32_t)0x3)<<2; //Enable ports A,B
RCC->APB1ENR |= ((uint32_t)0x1)<<14; //ENABLE SPI2
}
void GPIO_init(void)
{
GPIOB->CRH &= ~(((uint32_t) 0xf) << 16) ; //PB12 OUTPUT - AFIO - PUSH PULL
GPIOB->CRH |= ((uint32_t) 0xb) << 16 ; //PB12 OUTPUT - AFIO - PUSH PULL //////NSS//////
GPIOB->CRH &= ~(((uint32_t) 0xf) << 20) ; //PB13 OUTPUT - AFIO - PUSH PULL
GPIOB->CRH |= ((uint32_t) 0xb) << 20 ; //PB13 OUTPUT - AFIO - PUSH PULL //////SCK//////
GPIOB->CRH &= ~(((uint32_t) 0xf) << 24) ; //PB14 OUTPUT - AFIO - PUSH PULL
GPIOB->CRH |= ((uint32_t) 0xb) << 24 ; //PB15 OUTPUT - AFIO - PUSH PULL //////MISO//////
GPIOB->CRH &= ~(((uint32_t) 0xf) << 28) ; //PB15 OUTPUT - AFIO - PUSH PULL
GPIOB->CRH |= ((uint32_t) 0xb) << 28 ; //PB15 OUTPUT - AFIO - PUSH PULL //////MOSI//////
GPIOA->CRH &= ~(((uint32_t) 0xf) << 0) ; //PB8 OUTPUT - GENERAL PURPUSE - PUSH PULL
GPIOA->CRH &= ~(((uint32_t) 0x1) << 0) ; //PB8 OUTPUT - GENERAL PURPUSE - PUSH PULL
GPIOA->CRH &= ~(((uint32_t) 0xf) << 4) ; //PB8 OUTPUT - GENERAL PURPUSE - PUSH PULL
GPIOA->CRH &= ~(((uint32_t) 0x1) << 4) ; //PB8 OUTPUT - GENERAL PURPUSE - PUSH PULL
}
void SPI_init(void)
{
SPI2->CR1 = 0x0000;
SPI2->CR1 |= ((uint16_t)0x1)<<4; // Fclk/4
//SPI1->CR1 |= ((uint16_t)0x1)<<8; // Enable SSI
SPI2->CR2 |= ((uint16_t)0x1)<<2;
SPI2->CR1 |= ((uint16_t)0x1)<<2; // Master mode
SPI2->CR1 |= ((uint16_t)0x1)<<15; // BIDIRECTION
SPI2->CR1 |= ((uint16_t)0x1)<<14; // TRANSMIT ONLY
SPI2->CR1 |= ((uint16_t)0x1)<<6; // SPI1 enable
}
void LCD_init(void)
{
NRES; //PULLS RESET PIN HIGH
RESET_DK; //PULLS DK PIN LOW - COMMAND MODE
RES; //PULLS RESET PIN LOW
delay();
NRES; //PULLS RESET PIN HIGH
}
void delay(void)
{
uint32_t volatile count = 0 ;
while( count < 100 )
{
count++;
}
}
What's really weird is that the LCD sometimes turns 1/3 of its pixels on when I push the reset button , and if I pushed more two times it turns the whole screen on (1/3 each time) and the same when I enter the debug mode.
So what is the wrong with my code?