QQ群里发布了这样一个面试题:
看到这样一个问题,群里讨论得很热闹,几位群友也给出了一些解答,主要有两种思路:
① 第一种思路是:依次输出相应电平,高、低电平持续的时间根据题目要求确定即可。关键代码如下(代码来自昵称为宋阳的群友):
- static void plus(uint16_t h_times, uint16_t l_times)
- {
- IO_HIGH();
- HAL_Delay(h_times);
- IO_LOW();
- HAL_Delay(l_times);
- }
-
- static void outplus(void)
- {
- plus(2, 1);
- plus(1, 2);
- plus(3, 1);
- plus(1, 1);
- plus(2, 1);
- plus(2, 1);
- plus(3, 0);
- }
实际测试结果:
② 第二种思路是:可以把这个波形看做数据(0x1A75B7)来看待,这样一来就可以通过一个GPIO来按照这个数据输出相应的高低电平就可以得到对应的波形。关键代码如下(代码来自@_GWD、上海-zak、习道道等群友):
- uint32_t out_data = 0x1A75B7;
- static void WaveOutput(uint32_t data)
- {
- int i;
- for (i = 0; i < 21; i++)
- {
- if (data & 0x100000)
- {
- IO_HIGH();
- }
- else
- {
- IO_LOW();
- }
- data <<= 1;
- HAL_Delay(1);
- }
- }
经过实测得到的波形与上面的方法得到的波形是一致的,都能满足题目的要求。
针对这个题目,似乎按照第一种方法能更快地做出来。但是,我觉得这道题目真正要考察的应该是第二种思路,因为这个思路就是软件I2C、SPI的套路呀,想要考察我们会不会使用GPIO模拟一些总线协议。
软件I2C的发送数据函数(代码来自:安富莱):
- /*
- *********************************************************************************************************
- * 函 数 名: i2c_SendByte
- * 功能说明: CPU向I2C总线设备发送8bit数据
- * 形 参: _ucByte : 等待发送的字节
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void i2c_SendByte(uint8_t _ucByte)
- {
- uint8_t i;
-
- /* 先发送字节的高位bit7 */
- for (i = 0; i < 8; i++)
- {
- if (_ucByte & 0x80)
- {
- I2C_SDA_1();
- }
- else
- {
- I2C_SDA_0();
- }
- i2c_Delay();
- I2C_SCL_1();
- i2c_Delay();
- I2C_SCL_0();
- if (i == 7)
- {
- I2C_SDA_1(); // 释放总线
- }
- _ucByte <<= 1; /* 左移一个bit */
- i2c_Delay();
- }
- }
软件SPI的发送数据函数(代码来自:安富莱):
- /*
- *********************************************************************************************************
- * 函 数 名: bsp_spiWrite0
- * 功能说明: 向SPI总线发送一个字节。SCK上升沿采集数据, SCK空闲时为低电平。
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void bsp_spiWrite0(uint8_t _ucByte)
- {
- uint8_t i;
-
- for(i = 0; i < 8; i++)
- {
- if (_ucByte & 0x80)
- {
- MOSI_1();
- }
- else
- {
- MOSI_0();
- }
- bsp_spiDelay();
- SCK_1();
- _ucByte <<= 1;
- bsp_spiDelay();
- SCK_0();
- }
- bsp_spiDelay();
- }
看看,是不是一样的套路。SPI、I2C是两块重中之重的知识,而且也是我们嵌入式笔试面试中的高频考点,需要我们反复去理解,吸收。
本篇文章相关的工程、资料已整理好,网盘下载,失效请去社区求助。
链接:https://pan.baidu.com/s/1_PGMEk9tlgnV2BEdlXydjw 提取码:gxh1