USART模块有同步模式,并且可以输出时钟,也就是可以用作SPI,但是USART速度都不快.比如2.625MHz(USART2),或者5.25MHz(USART1),当然我们板子上的USART2不能用.这么慢速的设备,适合用于像触摸芯片等慢速设备.而且他是基于串口的分频器,所以分频出来可以更精确某个频率(当然,SPI一般并不那么要求.) 我做了个表格,关于各种频率:
PCLK(Hz) | 42,000,000 | ||||||
16倍采样波特率计算 BRR=PCLK/Baud | |||||||
波特率设定 | 分频比>=1 | 计算结果 | 实际分频比 | 寄存器值(HEX) | 实际波特率 | 波特率误差 | 误差百分比 |
9,600 | 273.4375 | 4375 | 273.4375 | 1117 | 9600.00 | 0.00 | 0.000 |
19,200 | 136.71875 | 2187 | 136.6875 | 88B | 19204.39 | 4.39 | 0.023 |
38,400 | 68.359375 | 1093 | 68.3125 | 445 | 38426.35 | 26.35 | 0.069 |
115,200 | 22.78645833 | 364 | 22.75 | 16C | 115384.62 | 184.62 | 0.160 |
230,400 | 11.39322917 | 182 | 11.375 | B6 | 230769.23 | 369.23 | 0.160 |
1,000,000 | 2.625 | 42 | 2.625 | 2A | 1000000.00 | 0.00 | 0.000 |
2,000,000 | 1.3125 | 21 | 1.3125 | 15 | 2000000.00 | 0.00 | 0.000 |
16倍采样波特率计算 BRR=(PCLK+Baud/2)/Baud | |||||||
波特率设定 | 分频比>=1 | 计算结果 | 实际分频比 | 寄存器值 | 实际波特率 | 误差 | 误差百分比 |
9,600 | 273.4375 | 4375 | 273.4375 | 1117 | 9600.00 | 0.00 | 0.000 |
19,200 | 136.71875 | 2188 | 136.75 | 88C | 19195.61 | -4.39 | -0.023 |
38,400 | 68.359375 | 1094 | 68.375 | 446 | 38391.22 | -8.78 | -0.023 |
115,200 | 22.78645833 | 365 | 22.8125 | 16D | 115068.49 | -131.51 | -0.114 |
230,400 | 11.39322917 | 182 | 11.375 | B6 | 230769.23 | 369.23 | 0.160 |
1,000,000 | 2.625 | 42 | 2.625 | 2A | 1000000.00 | 0.00 | 0.000 |
2,000,000 | 1.3125 | 21 | 1.3125 | 15 | 2000000.00 | 0.00 | 0.000 |
8倍采样波特率计算 BRR=PCLK/Baud | |||||||
波特率设定 | 分频比>=1 | 计算结果 | 实际分频比 | 寄存器值(HEX) | 实际波特率 | 波特率误差 | 误差百分比 |
9,600 | 546.875 | 4375 | 546.875 | 2227 | 9600.00 | 0.00 | 0.000 |
19,200 | 273.4375 | 2187 | 273.375 | 1113 | 19204.39 | 4.39 | 0.023 |
38,400 | 136.71875 | 1093 | 136.625 | 885 | 38426.35 | 26.35 | 0.069 |
115,200 | 45.57291667 | 364 | 45.5 | 2D4 | 115384.62 | 184.62 | 0.160 |
230,400 | 22.78645833 | 182 | 22.75 | 166 | 230769.23 | 369.23 | 0.160 |
1,000,000 | 5.25 | 42 | 5.25 | 52 | 1000000.00 | 0.00 | 0.000 |
2,000,000 | 2.625 | 21 | 2.625 | 25 | 2000000.00 | 0.00 | 0.000 |
8倍采样波特率计算 (PCLK+Baud/2)/Baud | |||||||
波特率设定 | 分频比>=1 | 计算结果 | 实际分频比 | 寄存器值(HEX) | 实际波特率 | 波特率误差 | 误差百分比 |
9,600 | 546.875 | 4375 | 546.875 | 2227 | 9600.00 | 0.00 | 0.000 |
19,200 | 273.4375 | 2188 | 273.5 | 1114 | 19195.61 | -4.39 | -0.023 |
38,400 | 136.71875 | 1094 | 136.75 | 886 | 38391.22 | -8.78 | -0.023 |
115,200 | 45.57291667 | 365 | 45.625 | 2D5 | 115068.49 | -131.51 | -0.114 |
230,400 | 22.78645833 | 182 | 22.75 | 166 | 230769.23 | 369.23 | 0.160 |
1,000,000 | 5.25 | 42 | 5.25 | 52 | 1000000.00 | 0.00 | 0.000 |
2,000,000 | 2.625 | 21 | 2.625 | 25 | 2000000.00 | 0.00 | 0.000 |
比如我们要发生2MHz的SPI时钟,那么波特率应该是2000000bps.要使能CLKEN引脚,CLKEN才能输出.比如我的配置.
一般来说,SPI还是MSB的,但是串口是LSB的,但是串口这里不能MSB先发,所以也有一些其他限制.特别注意的是,CLKEN必须有,才能输出SCLK,然后TX就是MOSI,RX就是MISO.为什么要M位,这个在串口模式下,他是表示9位数据,但是SPI模式是发8Bit,因为时钟只发了8Bit,最后一个被忽略了.波特率稍微高一些,SPI设备肯定比串口设备更能接受数据啊,所以BRR我们设置0x15,也就是2MHz.因为之前学习了BitBand,所以这里有一些涉及BitBand的寄存器配置.但是有一些注释,也是很方便的.
void DUSART_Init(void) { GPIOA_B->MODER.MODER2 = 0x02; //PA2 GPIOA_B->OSPEEDR.OSPEEDR2 = 0x02; GPIOA_B->PUPDR.PUPDR2 = 0x01; GPIOA_B->MODER.MODER4 = 0x02; //PA4 GPIOA_B->OSPEEDR.OSPEEDR4 = 0x02; GPIOA_B->PUPDR.PUPDR4 = 0x01; GPIOA_B->AFR[0].AFR2 = 0x07; //Pin Mux GPIOA_B->AFR[0].AFR4 = 0x07; USART2->BRR = 0x00000015; //2MHz USART2->CR1 = 0x00003008; //EN + TX + 9B(8B For SPI) USART2->CR2 = 0x00000800; //CLKOUT }
然后可以做一个测试示例.
void test_spi_usart(void) { uint8_t i = 0; for(i = 0x00; i < 0xff; i++) { while(!(USART2_B->SR.TC)); GPIOD_B->ODR.ODR15 = 0x01; Delay(1); GPIOD_B->ODR.ODR15 = 0x00; USART2->DR = i; } }
就可以发SPI了,不过是LSB,不支持MSB的.
太好,完美解决了我SPI不够用的问题。
@Joy 这个SPI速度比较慢的.