江科大學(xué)習(xí)筆記 _15.硬件SPI
?

W25Q64:地址寬度24位,3字節(jié) 8M->塊->扇區(qū)->頁
??8 * 1024 *1024 范圍:00 00 00H--7F FF FFH (8MB)
?
8M分為128個(gè)塊,每個(gè)塊(64K) 塊0-塊127,
(8*1024 *1024 /64*1024) = 128 范圍:xx 00 00 H--xx FF FFH(64KB)
?
64K分為16個(gè)扇區(qū),每個(gè)扇區(qū)(4k),扇區(qū)0--扇區(qū)15
(64*1024/4*1024) = 16 范圍:xx x0 00h -- xx xF FFh (4KB)
?
4K分為16個(gè)頁,每個(gè)頁(256字節(jié)),頁0--頁15
(4*1024/256) = 16 范圍:xx xx 00h -- xx xx FFh (256)
?
?
?
?
?
?

STM32單片機(jī)為主機(jī),W25Q64為從機(jī)
CS:片選
DO:從機(jī)輸出
CLK:時(shí)鐘
DI:從機(jī)輸入
?
?
?
?

SPI和IIC都是高位先行
串口是低位先行
?
每次交換8或16位數(shù)據(jù)
SPI時(shí)鐘 = fPCLK/分頻系數(shù)(2,4,8,16,32,64,128,256),
SPI1和SPI2掛載總線不同SPI1->APB2(72M),SPI2>APB1(36M)
?

?
TDR/RDR/TXE/RXNE
TXE:TDR數(shù)據(jù)全部移入移位寄存器,置1
RXNE:移位寄存器數(shù)據(jù)全部移入RDR,置1
?

CPOL = 1;CPHA = 1,SPI模式3 SCK默認(rèn)高電平
?
檢測到TXE = 1,TDR為空 ?-> ?軟件寫入0XF1至SPI_DR -> TDR的值變?yōu)镕1,TXE變?yōu)?
RXNE置1后,讀出接收到的第一個(gè)數(shù)據(jù), 再寫入下一個(gè)字節(jié)數(shù)據(jù)
交換字節(jié)時(shí)序
1.?等待TXE為1
2.?寫入發(fā)送的數(shù)據(jù)至TDR
3.?等待RXNE為1
4.?讀取RDR接收的數(shù)據(jù),重復(fù)這4步
?
?
?
硬件SPI配置步驟
1.?開始時(shí)鐘SPI、GPIO
2.?初始化GPIO口,SCK/MOSI推挽輸出,MISO為上拉輸入,SS通用推挽輸出
3.?配置SPI外設(shè)
4.?SPI_Cmd
?
void?MySPI_Init(void)
{
? ? RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
? ? RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);
?
? ? GPIO_InitTypeDef?GPIO_InitStruct;
? ? GPIO_InitStruct.GPIO_Mode?=?GPIO_Mode_Out_PP;
? ? GPIO_InitStruct.GPIO_Pin?=?SS;
? ? GPIO_InitStruct.GPIO_Speed?=?GPIO_Speed_50MHz;
? ? GPIO_Init(SPI_Port, &GPIO_InitStruct);
?
? ? GPIO_InitStruct.GPIO_Mode?=?GPIO_Mode_AF_PP;
? ? GPIO_InitStruct.GPIO_Pin?=?SCK|MOSI;
? ? GPIO_InitStruct.GPIO_Speed?=?GPIO_Speed_50MHz;
? ? GPIO_Init(SPI_Port, &GPIO_InitStruct);
?
? ? GPIO_InitStruct.GPIO_Mode?=?GPIO_Mode_IPU;
? ? GPIO_InitStruct.GPIO_Pin?=?MISO;
? ? GPIO_InitStruct.GPIO_Speed?=?GPIO_Speed_50MHz;
? ? GPIO_Init(SPI_Port, &GPIO_InitStruct);
?
? ? SPI_InitTypeDef?SPI_InitStruct;
? ? SPI_InitStruct.SPI_Mode?=?SPI_Mode_Master;//主機(jī)or從機(jī)
? ? SPI_InitStruct.SPI_DataSize?=?SPI_DataSize_8b;//交換數(shù)據(jù)8位or16位
? ? SPI_InitStruct.SPI_FirstBit?=?SPI_FirstBit_MSB;?//高位開始o(jì)r低位開始 ?
? ? SPI_InitStruct.SPI_Direction?=?SPI_Direction_2Lines_FullDuplex;//全雙工 ? ?
? ? SPI_InitStruct.SPI_BaudRatePrescaler?=?SPI_BaudRatePrescaler_128;//預(yù)分頻
? ? SPI_InitStruct.SPI_CPHA?=?SPI_CPHA_1Edge;//第一個(gè)邊沿采樣or第二個(gè)邊沿采樣
? ? SPI_InitStruct.SPI_CPOL?=?SPI_CPOL_Low;//默認(rèn)時(shí)鐘極性低or高
? ? SPI_InitStruct.SPI_NSS?=?SPI_NSS_Soft; ? ?
? ? SPI_InitStruct.SPI_CRCPolynomial?=?7;
? ? SPI_Init(SPI1,&SPI_InitStruct);
? ? SPI_Cmd(SPI1, ENABLE);
? ? MySPI_W_SS(1);//默認(rèn)不選中從機(jī)
}
?
?
交換字節(jié)時(shí)序
1.等待TXE為1
2.寫入發(fā)送的數(shù)據(jù)至TDR
3.等待RXNE為1
4.讀取RDR接收的數(shù)據(jù),重復(fù)這4步
?
uint8_t?MySPI_SwapByte(uint8_t?ByteSend)
{
? ? while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) ==?RESET);
? ? //等待TXE為1
? ? SPI_I2S_SendData(SPI1, ByteSend);
? ? //寫發(fā)送的數(shù)據(jù)至TDR
?
? ? while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) ==?RESET);
? ? //等待RXNE為1(發(fā)送完成即接收完成)
? ? return?SPI_I2S_ReceiveData(SPI1);
? ? //讀取RDR接收數(shù)據(jù)
}
?
需要考慮標(biāo)志位是否會自動清除,如果不自動清除,則要手動清除
?