[solved]About the SPI clock dividing
Posted: Wed Dec 03, 2014 1:59 am
Hi, everyone. I'm using the ESP8266 chip to drive the LED Strip that using ucs1903 controller. The ucs1903 controller use a single line communication protocol, and I have implemented a version based on GPIO bit-banging, now I'm going to use the SPI to simulate the timming to make things more efficient. But when I refer to the official HSPI demo, http://bbs.espressif.com/viewtopic.php?f=15&t=56&p=198&hilit=hspi#p198, I was confused on the SPI clock dividing. I have make some tries as bellow:
void ICACHE_FLASH_ATTR
ucs1903_spi_init()
{
uint32 regvalue;
//refer to http://www.esp8266.com/viewtopic.php?t=669&p=3624
//bit9 in PERIPHS_IO_MUX should decide whether SPI clock is derived from system clock
//but nothing is change by clear bit9 or set it.
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9
//PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure io to spi mode
//PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure io to spi mode
//PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure io to spi mode
SET_PERI_REG_MASK(SPI_USER(1), SPI_CS_SETUP | SPI_CS_HOLD | SPI_USR_COMMAND | SPI_USR_MOSI);
CLEAR_PERI_REG_MASK(SPI_USER(1), SPI_FLASH_MODE);
//clear Daul or Quad lines transmission mode
CLEAR_PERI_REG_MASK(SPI_CTRL(1), SPI_QIO_MODE |SPI_DIO_MODE | SPI_DOUT_MODE | SPI_QOUT_MODE);
//I send out 0xaa 0x55 in ucs1903_spi_test function to genertate a square wave on SPI MOSI pin
//I make some changes here on the SPI clock dividing configuration register and observe changes on the SPI MOSI pin
//When I change the value of N field in the register,
//N == 3, H == 1, L == 3, SPI MOSI output 555.5kHz square wave signal
//N == 2, H == 1, L == 3, SPI MOSI output 634.8kHz square wave signal
//N == 1, H == 1, L == 3, SPI MOSI output 740.6kHz square wave signal
//N == 0, SPI MOSI always high
//When N == 3, H and L are non zero value, the SPI MOSI always output 555.5kHz square wave signal
// so I wonder is anyone here know about the meaning of each field in the SPI clock dividing register and kind to tell me how can I get a 4MHz SPI clock here. Thanks.
WRITE_PERI_REG(SPI_CLOCK(1),
((0 & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) |
((3 & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) |
((1 & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) |
((3 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S)); //clear bit 31,set SPI clock div
//set 8bit output buffer length, the buffer is the low 8bit of register"SPI_FLASH_C0"
WRITE_PERI_REG(SPI_USER1(1),
((7 & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S)|
((7 & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S));
}
void ICACHE_FLASH_ATTR
ucs1903_spi_send(uint8 data)
{
uint32 regvalue;
while(READ_PERI_REG(SPI_CMD(1)) & SPI_USR);
CLEAR_PERI_REG_MASK(SPI_USER(1), SPI_USR_MOSI | SPI_USR_MISO);
//SPI_FLASH_USER2 bit28-31 is cmd length,cmd bit length is value(0-15)+1,
// bit15-0 is cmd value.
WRITE_PERI_REG(SPI_USER2(1), ((7 & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) | data);
SET_PERI_REG_MASK(SPI_CMD(1), SPI_USR);
}
void ICACHE_FLASH_ATTR
ucs1903_spi_test()
{
while(1) {
ucs1903_spi_send(0xaa);
ucs1903_spi_send(0x55);
}
}
void ICACHE_FLASH_ATTR
ucs1903_spi_init()
{
uint32 regvalue;
//refer to http://www.esp8266.com/viewtopic.php?t=669&p=3624
//bit9 in PERIPHS_IO_MUX should decide whether SPI clock is derived from system clock
//but nothing is change by clear bit9 or set it.
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9
//PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure io to spi mode
//PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure io to spi mode
//PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure io to spi mode
SET_PERI_REG_MASK(SPI_USER(1), SPI_CS_SETUP | SPI_CS_HOLD | SPI_USR_COMMAND | SPI_USR_MOSI);
CLEAR_PERI_REG_MASK(SPI_USER(1), SPI_FLASH_MODE);
//clear Daul or Quad lines transmission mode
CLEAR_PERI_REG_MASK(SPI_CTRL(1), SPI_QIO_MODE |SPI_DIO_MODE | SPI_DOUT_MODE | SPI_QOUT_MODE);
//I send out 0xaa 0x55 in ucs1903_spi_test function to genertate a square wave on SPI MOSI pin
//I make some changes here on the SPI clock dividing configuration register and observe changes on the SPI MOSI pin
//When I change the value of N field in the register,
//N == 3, H == 1, L == 3, SPI MOSI output 555.5kHz square wave signal
//N == 2, H == 1, L == 3, SPI MOSI output 634.8kHz square wave signal
//N == 1, H == 1, L == 3, SPI MOSI output 740.6kHz square wave signal
//N == 0, SPI MOSI always high
//When N == 3, H and L are non zero value, the SPI MOSI always output 555.5kHz square wave signal
// so I wonder is anyone here know about the meaning of each field in the SPI clock dividing register and kind to tell me how can I get a 4MHz SPI clock here. Thanks.
WRITE_PERI_REG(SPI_CLOCK(1),
((0 & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) |
((3 & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) |
((1 & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) |
((3 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S)); //clear bit 31,set SPI clock div
//set 8bit output buffer length, the buffer is the low 8bit of register"SPI_FLASH_C0"
WRITE_PERI_REG(SPI_USER1(1),
((7 & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S)|
((7 & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S));
}
void ICACHE_FLASH_ATTR
ucs1903_spi_send(uint8 data)
{
uint32 regvalue;
while(READ_PERI_REG(SPI_CMD(1)) & SPI_USR);
CLEAR_PERI_REG_MASK(SPI_USER(1), SPI_USR_MOSI | SPI_USR_MISO);
//SPI_FLASH_USER2 bit28-31 is cmd length,cmd bit length is value(0-15)+1,
// bit15-0 is cmd value.
WRITE_PERI_REG(SPI_USER2(1), ((7 & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) | data);
SET_PERI_REG_MASK(SPI_CMD(1), SPI_USR);
}
void ICACHE_FLASH_ATTR
ucs1903_spi_test()
{
while(1) {
ucs1903_spi_send(0xaa);
ucs1903_spi_send(0x55);
}
}