Author Topic: SPI on the STM32 USART  (Read 19042 times)

0 Members and 1 Guest are viewing this topic.

sgomes

  • Newbie
  • Posts: 9
SPI on the STM32 USART
« on: 07 February, 2010, 04:19:25 PM »
I've been playing with the STM32 lately and I have to say I'm quite impressed.  However I found the first tiny little issue that is frustrating.  The SPI peripheral.  I'm using the Nokia 6100/6610 display and it has this odd 9-bit data frame.  Unfortunately the STM32 will only allow 8 or 16 bit frames.  So it looks like I will have to bit-bang the SPI.  No big deal I know but I'm one for throwing a byte at a register and letting my code get on with things.  Having to sit around and babysit the SPI is frustrating.

Anyone have a clever idea how to use the 16-bit mode to produce a 9-bit frame?  Hmmm I just had a thought....maybe use a USART in synchronous mode somehow....  :)||

Shannon

peteh

  • Administrator
  • phpBB Senior member
  • *****
  • Posts: 512
Re: The first chink in the armor for STM32
« Reply #1 on: 07 February, 2010, 05:27:58 PM »
The USARTS on the STM32 can be run in synchronous mode where they behave exactly like a SPI peripheral and they support 8 or 9 data bits.

I have not tried this - just seen it in the reference book.

sgomes

  • Newbie
  • Posts: 9
Re: The first chink in the armor for STM32
« Reply #2 on: 07 February, 2010, 11:32:27 PM »
yep exactly right.  What a relief it was to read the reference manual and find that they have all the bits for doing 8 or 9 bit SPI via the USARTs.  Man this is a fantastic chip!

For the record:

//turn on the clock
RCC_APB1ENR |= RCC_APB1ENR_USART2EN;

//PA2 (MOSI) to alternate function push-pull
mode = (uint32_t)0x09 << GPIOA_CRL_CNF2_MODE2_BIT;
temp = GPIOA_CRL & ~GPIOA_CRL_CNF2_MODE2_MASK;
GPIOA_CRL = temp | mode;

//PA3 (MISO) to alternate function input floating
mode = (uint32_t)0x04 << GPIOA_CRL_CNF3_MODE3_BIT;
temp = GPIOA_CRL & ~GPIOA_CRL_CNF3_MODE3_MASK;
GPIOA_CRL = temp | mode;

//PA4 (SCK) to alternate function push-pull
mode - (uint32_t)0x09 << GPIOA_CRL_CNF4_MODE4_BIT;
temp = GPIOA_CRL & ~GPIOA_CRL_CNF4_MODE4_MASK;
GPIOA_CRL = temp | mode;

//set clock rate to 6MHz;
USART2_BRR  = 36000000L/6000000L;  //APB1 bus max speed is 36MHz
USART2_CR1 |= (USART2_CR1_RE | USART2_CR1_TE | USART2_CR1_M);    // RX, TX enable, 9-bit
USART2_CR2 |= USART2_CR2_CLKEN;  //enable SCK pin  CPOL and CPHA are also in this register
USART2_CR1 |= USART2_CR1_UE;       // USART enable
 
//interrupts can also be enabled in the USART2_CR1 register

Shannon

sgomes

  • Newbie
  • Posts: 9
Re: The first chink in the armor for STM32
« Reply #3 on: 08 February, 2010, 03:12:14 PM »
Just discovered another caveat.  The SPI bus is a MSB first bus and the USART is a LSB first bus.  So to use the USART in SPI mode you'll have to reverse the order of the data bits before stuffing it into the transmit register.

Something like this for 8-bits:

c = (c & 0x0F) << 4 | (c & 0xF0) >> 4;
c = (c & 0x33) << 2 | (c & 0xCC) >> 2;
c = (c & 0x55) << 1 | (c & 0xAA) >> 1;

probably converting to assembly and optimizing it might make it faster.

sgomes

  • Newbie
  • Posts: 9
Re: The first chink in the armor for STM32
« Reply #4 on: 10 February, 2010, 10:36:26 PM »
I asked ST about this issue of MSB first vs. LSB first.  Apparently it is true that if using the USART for SPI communication you DO have to reverse the order of the bits.  However there is an easy way to do it.  I've copied his response below:

Quote
Dear User,
Please find here below latest information concerning the request R10060100

You are correct. There is no reverse bit in the USART registers.

There is, however, a 1 clock cycle Thumb2 instruction that will do it for you. RBIT. There's also a macro in the STM32 Standard library That allows you to call the assy lang. instruction from C.

A copy of it below:

Code: [Select]
/**
 * @brief  Reverse bit order of value
 *
 * @param  uint32_t value to reverse
 * @return uint32_t reversed value
 *
 * Reverse bit order of value
 */
uint32_t __RBIT(uint32_t value)
{
  __ASM("rbit r0, r0");
  __ASM("bx lr");
}

peteh

  • Administrator
  • phpBB Senior member
  • *****
  • Posts: 512
Re: The first chink in the armor for STM32
« Reply #5 on: 10 February, 2010, 10:49:52 PM »
That is very handy. thanks for passing that on.

reva

  • Newbie
  • Posts: 3
Re: SPI on the STM32 USART
« Reply #6 on: 30 April, 2012, 07:47:09 AM »
Im trying to interface Nokia LCD 6610 to STM32L through sync USART. Though there is clock and data on MOSI and SCK pins LCD isnt displaying anything. Below is the code i've used for transfer of data through USART
USART_DeInit(USART2);
   USART_InitStructure.USART_BaudRate =0x02255100;//0x0001C200;   // baud   rate=115200
   USART_InitStructure.USART_WordLength =USART_WordLength_9b;
   USART_InitStructure.USART_StopBits =USART_StopBits_1;
   USART_InitStructure.USART_Parity=USART_Parity_No;
   USART_InitStructure.USART_Mode=USART_Mode_Tx;
   USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
   USART_Init(USART2, &USART_InitStructure);

   USART_ClkInitStructure.USART_Clock=   USART_Clock_Enable;
   USART_ClkInitStructure.USART_CPOL=USART_CPOL_Low;
   USART_ClkInitStructure.USART_CPHA=USART_CPHA_1Edge;
   USART_ClkInitStructure.USART_LastBit=USART_LastBit_Enable;
   USART_ClockInit(USART2, &USART_ClkInitStructure);
     
   USART_Cmd(USART2,ENABLE);

reva

  • Newbie
  • Posts: 3
Re: SPI on the STM32 USART
« Reply #7 on: 30 April, 2012, 07:51:56 AM »
Below is the code implemented for data transfer through USART
void WriteSpiData(unsigned int data)
{
   
 
   data = (data & 0x0F) << 4 | (data & 0xF0) >> 4;
    data = (data & 0x33) << 2 | (data & 0xCC) >> 2;
    data = (data & 0x55) << 1 | (data & 0xAA) >> 1;   
   data = ((data << 1 ) | 0x0001);   
   //data=(data  | 0X0100);
     USART_SendData(USART2, data);

     while(USART_GetFlagStatus(USART2, USART_FLAG_TXE )==RESET);


}

void WriteSpiCommand(unsigned int data)
{
   
   
   
    data = (data & 0x0F) << 4 | (data & 0xF0) >> 4;
    data = (data & 0x33) << 2 | (data & 0xCC) >> 2;
    data = (data & 0x55) << 1 | (data & 0xAA) >> 1;
    data = ((data << 1 ) & ~0x0001);
//data=(data & ~0X0100);
     USART_SendData(USART2, data);

     while(USART_GetFlagStatus(USART2, USART_FLAG_TXE  )==RESET);

}


Please help me with this

reva

  • Newbie
  • Posts: 3
Re: SPI on the STM32 USART
« Reply #8 on: 01 May, 2012, 01:41:28 PM »
hey!! i changed the settings to USART1 .. a better USART in terms of speed ... and..... behold its workin!   ... jus done wid my demo :)) ...
Thanks guys  m/...........
really thank sgomes ... the data reversal was quite helpful :)
CHANGED USART settings
USART_DeInit(USART1);
   USART_InitStructure.USART_BaudRate =0x00011114;//0x0001C200;   // baud   rate=115200
   USART_InitStructure.USART_WordLength =USART_WordLength_9b;
   USART_InitStructure.USART_StopBits =USART_StopBits_1;
   USART_InitStructure.USART_Parity=USART_Parity_No;
   USART_InitStructure.USART_Mode=USART_Mode_Tx;
   USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
   USART_Init(USART1, &USART_InitStructure);

   USART_ClkInitStructure.USART_Clock=   USART_Clock_Enable;
   USART_ClkInitStructure.USART_CPOL=USART_CPOL_Low;
   USART_ClkInitStructure.USART_CPHA=USART_CPHA_1Edge;
   USART_ClkInitStructure.USART_LastBit=USART_LastBit_Enable;
   USART_ClockInit(USART1, &USART_ClkInitStructure);
      USART_Cmd(USART1,ENABLE);

Micromouseonline Forum

Re: SPI on the STM32 USART
« Reply #8 on: 01 May, 2012, 01:41:28 PM »