#申请原创#
GPIO是所有单片机都提供的一种资源。除了作为简单的开关、输入输出量以外,还会经常被用作串行通讯手段。我个人就超喜欢用GPIO口模拟I2C、SPI方式,来驱动OLED、TFT之类的液晶显示屏,原因很简单,一是例程容易获得和转化,而是不用考虑使用专用外设通讯过程中过多的、复杂的处理。比如使用I2C,要处理中断、处理中的通讯状态等信息。像之前用过的一款单片机,使用I2C驱动OLED,结果通讯过程中要通过状态值判断通讯处于哪个阶段、下一步要收发什么数据等,由于是中断方式,需要记录很多信息,来保证数据通讯的连续性。远不如一次性,通过模拟来完成。
这一次一样,准备使用GPIO模拟SPI通讯,因为不使用标准SPI外设,通讯速度只受系统工作频率的影响。也就是说系统工作频率越高,通讯速度越快。根据用户手册,N32G430C8L7的最高工作频率是128MHz,单个时钟脉冲宽度相当于是7.8125纳秒级别。,按照SPI 通讯的特点,以模拟SPI的通讯时钟,需要操作两回GPIO口,通过引脚电平的变化,模拟出SPI的工作时钟。那么就按照7.8125纳秒计算,模拟一个SPI时钟,就是15.625纳秒。而实际上,由于代码上的处理,我感觉N32G430C8L7的GPIO口未必能做出这么高频率的时钟信号。为了验证,以最简单的GPIO Toggle无时间延迟方式方式输出固定的脉冲,并用示波器测试(我的示波器带宽是200M的,估计也是紧巴巴啊)。
主程序很简单,就是交替在LED1所在的GPIO扣上输出高低电平,由于while(1)本身设计条件判断和执行点跳转,对输出的速度会有影响。
int main(void) {
LED_Initialize(LED1_GPIO_PORT, LED1_GPIO_PIN, LED1_GPIO_CLK);
LED_Initialize(LED2_GPIO_PORT, LED2_GPIO_PIN | LED3_GPIO_PIN, LED2_GPIO_CLK);
LED_Off(LED2_GPIO_PORT, LED1_GPIO_PIN | LED2_GPIO_PIN | LED3_GPIO_PIN);
LED_On(LED2_GPIO_PORT, LED2_GPIO_PIN | LED3_GPIO_PIN);
SysTick_Delay_Ms(1000);
LED2_OFF;
LED3_OFF;
while(1) {
LED_Toggle(LED1_GPIO_PORT, LED1_GPIO_PIN);
}
}
开发板上的LED使用的是PA1。实测结果如下图所示: 脉冲宽度大约500nS。为了确认,再次以每次每个电平维持1毫秒,然后交替执行来输出脉冲, while(1) {
LED1_OFF;
SysTick_Delay_Ms(1);
LED1_ON;
SysTick_Delay_Ms(1);
}
理论结果应该是2毫秒的时钟周期,测试结果如下, 与理论结果一致,说明系统延时很准确啊,也侧面说明系统时钟也是准确无误的。从波形上看,500nS的那个可不是标准的矩形波,怀疑示波器的测量季度不够。为了验证之前的500nS是否准确,朱本再加入计数处理代码来代替刚才的系统延时处理。代码修改如下: while(1) {
LED1_OFF;
for (cnt=0; cnt<50; cnt++);
LED1_ON;
for (cnt=0; cnt<50; cnt++) ;
}
实测波形如下: 大概3.4微秒的样子。计数调整到500后,实测波形如下, 大概33微妙的样子,所以500ns的那个,确实有有出入的。 按照上面的测试结果,以GPIO模拟SPI输出脉冲,最小脉宽应该是在330纳秒左右的。后面我会用这种模拟速度测试SPI接口的TFT显示屏的显示处理。 本文最后,再对国民技术的开发板点个赞!板子简洁明快,GPIO输出的排针引脚说明信息印字清晰,非常方便快速查找和确认,提供的用户按钮个LED也足够多了。一如既往的国民技术风格,非常喜欢啊。另外所有资料,在官方网站配偶值期权,方便下载,真的没的说,是真的好方便!一个产品的好坏,售后、技术支持是相当重要的一个评价点。期待国民技术走自己的路,越来越好! |