STM8S001J3 由于 VCAP 的需要因此少了一支 I/O 引脚,跟另外 2 颗 8 引脚的 STM8 比较起来少了 PB7,而这一支引脚的复用功能是 SPI 的 MISO,因此对于 STM8S001J3 来说 SPI 是没有 MISO 引脚的。
SPI 的 CPOL 与 CPHA 设定决定了四种时序关系:
CPOL CLOCK POLARITY 时钟极性
0 SCK空闲状态保持低电位
1 SCK空闲状态保持高电位
CPHA CLOCK PHASE 时钟相位
0 SCK时钟的第一个边缘进行数据采集
1 SCK时钟的第二个边缘进行数据采集
一般比较常用的似乎是 CPOL = 0 , CPHPA = 0,比如说外接 74HC595 这类的 8 位串行入并行出的移位寄存器就需要做这样的设定,也就是在时钟上升缘时将数据移入寄存器内。
由于后面我打算连接 MAX7219 显示模块,因此先实现一个 SPI 的测试程序来熟悉一下功能,我使用逻辑分析仪采集数据的输出,程序中让 STM8S001J3 由 SPI 引脚输出 0x01、0x02、0x04、0x08、0x10、0x20、0x40、0x80 数据,NSS 引脚由程序控制输出。测试程序中有一个需要注意的地方,由于 MOSI 这支引脚也在 pin8 与烧录使用的 SWIM 同一支脚,因此程序的一开始需要先加上一个 5 秒的延时代码。
SPI 初始化:
- SPI_Init(SPI_FIRSTBIT_MSB, // 高位在前
- SPI_BAUDRATEPRESCALER_2, // 传输速率为主时钟 1/2
- SPI_MODE_MASTER, // 主机模式
- SPI_CLOCKPOLARITY_LOW, // CPOL = 0
- SPI_CLOCKPHASE_1EDGE, // CPHA = 0
- SPI_DATADIRECTION_2LINES_FULLDUPLEX, // 全双工模式
- SPI_NSS_SOFT, // 软件管理 NSS
- 0x07); // CRC 校验
[color=rgb(51, 102, 153) !important]复制代码
逻辑分析仪数据采集:
在先前的实验没有留意 STM8S001J3 上电后的系统时钟缺省设定是多少?直觉上一直认为应该是内部 HSI 的 16MHz,而程序中 SPI 的传输速率设定在主时钟的 1/2,因此 SCK 频率应该是 8MHz,但是在逻辑分析仪采集的 SCK 频率却是 1MHz!
查询规格书看到了这样的说明:
原来芯片复位 (RESET) 之后的可编程分频器设定在 8,因此主时钟频率就是 2MHz,所以我所采集到的 SCK 频率就是 1MHz 没错。为了得到比较快速的传输速率,我在 main 回圈的开头增加了对时钟设定的函数,将时钟设定在最高的 16MHz。
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
运行结果也得到了预期的 8MHz:
一个错误的教训!我一开始是将 CLK_HSIPrescalerConfig() 函数放在延时 5 秒代码之前,然而编程烧录过一次之后的再次编程就失败了!难道这颗芯片变砖了?延时 5 秒的代码是官方提供的,这应该是在主频为 2MHz 的条件下计算的,然而目前在延时 5 秒前我就将主频设定在 16MHz,那是否延时的时间就只剩不到 1 秒呢?原本板子在上电后可以有足够的时间按下 IAR 上的编程动作,现在延时时间减少了,我假如按钮编程的动作快一点的话是否可以就救回这一颗芯片,让芯片可以重新再烧录呢?
在试了很多次之后我放弃了,还好我在 ST 天猫也买了芯片,只好换上芯片后继续后续的实验。
main 回圈:
- void main(void)
- {
- uint8_t Dta[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
- uint8_t idx = 0;
- /* -------------STM8S001 startup-------------- */
- /* delay for SWIM connection: ~5seconds */
- STARTUP_SWIM_DELAY_5S;
- /* configure unbonded pins */
- CONFIG_UNUSED_PINS_STM8S001;
- GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_FAST); // NSS
- GPIO_WriteHigh(GPIOA, GPIO_PIN_3);
- /* ------------------------------------------- */
- /*High speed internal clock prescaler: 1*/
- CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
- /* SPI configuration */
- SPI_DeInit();
- /* Initialize SPI in Slave mode */
- SPI_Init(SPI_FIRSTBIT_MSB, SPI_BAUDRATEPRESCALER_2, SPI_MODE_MASTER, SPI_CLOCKPOLARITY_LOW,
- SPI_CLOCKPHASE_1EDGE, SPI_DATADIRECTION_2LINES_FULLDUPLEX, SPI_NSS_SOFT,0x07);
- /* Enable the SPI*/
- SPI_Cmd(ENABLE);
- while (1)
- {
- while(SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET);
- GPIO_WriteLow(GPIOA, GPIO_PIN_3); // NSS = 0
- SPI_SendData(Dta[idx++]);
- if(idx == 8) idx = 0;
- GPIO_WriteHigh(GPIOA, GPIO_PIN_3); // NSS = 1
- }
- }
[color=rgb(51, 102, 153) !important]复制代码
| 本文转载于【STM8-SO8】05-SPI的使用
http://www.stmcu.org.cn/module/forum/thread-619406-1-1.html
|