平头哥RVB2601板子-SPI测试
<p>通过原理图资料理解到OLED的控制芯片为SSD1309,该芯片与SPI1接口连接,根据程序源代码也可以看到使用的也是SPI总线。于是就像使用该芯片进行测试。因为CH2601的资料十分的匮乏,所有的参考都是通过参考例程。</p><p>与SPI有关的例程主要参考:W800芯片的例程,w800_at_port.c和SPI.C驱动例程。我于是参考该例程来修改OLED.C例程。为查看例程中只需要修改三个地方就可以了。</p>
<pre>
<code class="language-cpp">static void oled_gpio_init()
{
//
// csi_gpio_pin_init(&pin_clk, PA28);
// csi_gpio_pin_dir(&pin_clk, GPIO_DIRECTION_OUTPUT);
// csi_gpio_pin_init(&pin_mosi, PA29);
// csi_gpio_pin_dir(&pin_mosi, GPIO_DIRECTION_OUTPUT);
// csi_gpio_pin_init(&pin_cs, PA27);
// csi_gpio_pin_dir(&pin_cs, GPIO_DIRECTION_OUTPUT);
// csi_gpio_pin_init(&pin_miso, PA30); //dc
// csi_gpio_pin_dir(&pin_miso, GPIO_DIRECTION_OUTPUT);
int ret= 0;
ret = csi_spi_init(&spi_handle, 1);
if (ret < 0) {
printf("csi spi init failed\r\n");
return NULL;
}
csi_spi_mode(&spi_handle, SPI_MASTER);
ret = csi_spi_baud(&spi_handle, 500000);
LOGD(TAG, "#######################spi speed:%d\r\n", ret);
csi_spi_cp_format(&spi_handle, SPI_FORMAT_CPOL0_CPHA0);
csi_spi_frame_len(&spi_handle, SPI_FRAME_LEN_8);
csi_spi_select_slave(&spi_handle, 1);
#ifdef SPI_USE_DMA
csi_spi_attach_callback(&spi_handle, spi_event_cb, NULL);
csi_spi_link_dma(&spi_handle, NULL, &spi_recv_dma);
#endif
}
static void lcd_cs(uint8_t d)
{
if (d == 1) {
csi_gpio_pin_write(&pin_cs, GPIO_PIN_HIGH);
} else {
csi_gpio_pin_write(&pin_cs, GPIO_PIN_LOW);
}
}
//static void lcd_dc(uint8_t d)
//{
// if (d == 1) {
// csi_gpio_pin_write(&pin_miso, GPIO_PIN_HIGH);
// } else {
// csi_gpio_pin_write(&pin_miso, GPIO_PIN_LOW);
// }
//}
//
//static void lcd_sclk(uint8_t d)
//{
// if (d == 1) {
// csi_gpio_pin_write(&pin_clk, GPIO_PIN_HIGH);
// } else {
// csi_gpio_pin_write(&pin_clk, GPIO_PIN_LOW);
// }
//}
//
//static void lcd_sdin(uint8_t d)
//{
// if (d == 1) {
// csi_gpio_pin_write(&pin_mosi, GPIO_PIN_HIGH);
// } else {
// csi_gpio_pin_write(&pin_mosi, GPIO_PIN_LOW);
// }
//}
void Write_Command(unsigned char Data)
{
unsigned char i;
int32_t ret = 0;
lcd_cs(0);
ret = csi_spi_send(&spi_handle, &Data, 1, AOS_WAIT_FOREVER);
if (ret < 0) {
LOGD("at spi", "send cmd err");
}
// lcd_dc(0);
// for (i = 0; i < 8; i++) {
// lcd_sclk(0);
// lcd_sdin((Data & 0x80) >> 7);
// Data = Data << 1;
// lcd_sclk(1);
// }
// lcd_dc(1);
lcd_cs(1);
}
void Write_Data(unsigned char Data)
{
unsigned char i;
int32_t ret = 0;
lcd_cs(0);
ret = csi_spi_send(&spi_handle, &Data, 1, AOS_WAIT_FOREVER);
if (ret < 0) {
LOGD("at spi", "send cmd err");
}
// lcd_dc(1);
// for (i = 0; i < 8; i++) {
// lcd_sclk(0);
// lcd_sdin((Data & 0x80) >> 7);
// Data = Data << 1;
// lcd_sclk(1);
// }
// lcd_dc(1);
lcd_cs(1);
}
#endif</code></pre>
<p>修改完成后写入ch2601芯片,但我觉得完成的时候,发现屏幕没有任何的反应。那我就想开启调式模式。但是诡异的事情出现了。</p>
<p>首先,是我使用CDK在程序main.c中加入断点。</p>
<p> 但是无论这么样也无法中断。不论是直接开始还是开始下载都不能进入中断。</p>
<p> 更诡异的是:无论在程序的任何地方都不能进入“断点”!而且不管使用什么样的编译也不行。</p>
<p>后来我把LOGD函数进入到main方法中就可以。但是在其它方法中就不行。</p>
<p> 完整的代码片段如下:</p>
<pre>
<code class="language-cpp">/*
* Copyright (C) 2019-2020 Alibaba Group Holding Limited
*/
#include <stdlib.h>
#include <string.h>
#include <aos/aos.h>
#include "aos/cli.h"
#include "main.h"
#include "app_init.h"
#include "oled.h"
#define TAG "app"
int main(void)
{
board_yoc_init();
LOGD(TAG, "XXX %s\n", aos_get_app_version());
oled_init();
LOGD(TAG, "SPI end! YoC");
while (1) {
//LOGD(TAG, "Hello world! YoC");
aos_msleep(1000);
}
return 0;
}
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//Main Program
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// #define CONFIG_OLED_TEST
void oled_init()
{
LOGD(TAG, "SPI start! YoC");
oled_pinmux_init();
oled_gpio_init();
oled_initialize();
// lv_disp porting
/*Create a display buffer*/
lv_disp_buf_init(&disp_buf1, buf1, buf2, 64 * 128);
/*Create a display*/
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
disp_drv.buffer = &disp_buf1;
disp_drv.flush_cb = oled_flush;
disp_drv.rotated= 0;
lv_disp_drv_register(&disp_drv);
}
</code></pre>
<p>我的输出:</p>
<p> 就是看不到输出。不知道为什么。知道目前有一个星期的时间了,也没有任何进展。</p>
<p> </p>
补充内容 (2021-9-1 10:17):
最后终于知道为什么了,硬件设计没有回避SPIMISO引脚 <p>把oled_init函数放到main上边试试</p> <p>由于CH2601启用了XIP,代码直接运行在Flash上面,如果代码有修改,需要先烧录后才能运行断点。</p>
<p>具体步骤如下:</p>
<p>1、修改代码</p>
<p>2、编译</p>
<p>3、烧录</p>
<p>4、按系统复位键运行后,点击【Start Debugger】按键,调试器会连接设备并中断当前设备运行</p>
<p>5、在代码中增加断点,点击【Continue Debugger】按键,系统会继续运行,并停止在断点处。</p>
<p>注意,请确保断点位置还没执行到,否则将无法进入断点。如果断点在初始化阶段,可以在启动时加一个延时函数,确保在执行到断点之前就连接调试器。</p>
<p>例如,下面例程第20行增加5s延时,确保在执行到第21行断点之前,可以点击【Start Debugger】:</p>
<p> </p>
<p>辛苦辛苦,没资料的器件弄起来特别费劲</p>
未来开发者 发表于 2021-8-25 17:03
由于CH2601启用了XIP,代码直接运行在Flash上面,如果代码有修改,需要先烧录后才能运行断点。
具体步骤 ...
<p>按照你的提示已经试过了,除了能够得到点调式信息断点出不去!</p>
<p> </p>
<p>从你描述的现象来看像是没有成功编译你修改的文件,比如打印信息里有 app XXX,接着是app SPI end!YoC。而oled_init里的第一行“LOGD(TAG, "SPI start! YoC");"似乎没有被执行,如果先不考虑断点和调试的问题,你可以试试修改能够成功输出的LOGD代码,看输出是否变化,比如在”oled_init();“函数上边的”LOGD(TAG, "XXX %s\n", aos_get_app_version());“,试着把XXX改成其它字符看看会不会有变化 。</p>
<p>如果有变化,再看为什么没有进入oled_init();函数,因为函数里的第一句也是LOGD打印数据理论上没有道理什么都不显示,看你的代码main函数在上oled_init函数在下,main函数之前没见到oled_init的声明,这种情况理论应该编译不过,所以再试着把oled_init这个函数移到main上边看看。</p>
littleshrimp 发表于 2021-8-27 19:27
从你描述的现象来看像是没有成功编译你修改的文件,比如打印信息里有 app XXX,接着是app SPI end!YoC。而 ...
<p>我也觉得是没有被编译,但是我把函数名改了就不行了</p>
bigbat 发表于 2021-8-27 19:51
我也觉得是没有被编译,但是我把函数名改了就不行了
<p>试试改LOGD的输出看看结果有没有变化</p> littleshrimp 发表于 2021-8-27 23:10
试试改LOGD的输出看看结果有没有变化
<p>我把#ifdef语句都去掉了,而且LOGD这个宏,就是放在oled.h中定义的,main.c中是引用该文件的</p>
bigbat 发表于 2021-8-28 03:16
我把#ifdef语句都去掉了,而且LOGD这个宏,就是放在oled.h中定义的,main.c中是引用该文件的
<p>修改打印输出,串口接收到的数据有变化吗?</p> 本帖最后由 未来开发者 于 2021-8-29 20:48 编辑
<p>这种方法应该可以:<br />
<br />
1、右键工程,选择“Options for xxx”<br />
<br />
2、在配置页面中,点击【Debug】页签<br />
<br />
3、勾选【Load Application to Target】、【Auto Run】、【Stop at main】,如下图</p>
<p></p>
<p><br />
4、然后再次调试,就可以成功运行到断点处并且停下来了</p>
未来开发者 发表于 2021-8-29 20:46
这种方法应该可以:
1、右键工程,选择“Options for xxx”
2、在配置页面中,点击【Debug ...
<p></p>
<p>可以中断了,但是不知为什么程序跳过了LOGD指令。 </p>
bigbat 发表于 2021-8-26 08:50
按照你的提示已经试过了,除了能够得到点调式信息断点出不去!
<p>在使用调试的时候,我发现我的调试状态和文件中的描述不相同,程序烧录有直接电机调试按钮是不能开始调试,需要复位系统,让她正常运行起来,然后在你希望跟踪的地方设置断点,在点击开始调试按钮,当然,这时候我的系统是没有啥反映的,不过,条件满足的时候却会进入断点。</p>
<p>LCD显示的问题,我有个建议您参考一下,使用官方的驱动模式我觉得需要学习他的驱动编写方法,你可以考虑通过SPI接口的形式直接驱动这个LCD,如果可以的话,在进一步调试和系统的显示驱动挂钩,在使用lvgl图形库,感觉会好点。</p>
我爱下载 发表于 2021-8-30 16:05
LCD显示的问题,我有个建议您参考一下,使用官方的驱动模式我觉得需要学习他的驱动编写方法,你可以考虑通 ...
<p>谢谢,我改造驱动的目的就是SSD1309的资料比较少,而且就算有也比较麻烦。所以我就改一下它的数据发送我想就可以了。我这种方法在SSD1306下是成功的。</p>
<p>测试补充:在上面的测试中有几处需要补充,首先是引脚的初始化</p>
<pre>
<code class="language-cpp">static void oled_gpio_init()
{
//
// csi_gpio_pin_init(&pin_clk, PA28);
// csi_gpio_pin_dir(&pin_clk, GPIO_DIRECTION_OUTPUT);
// csi_gpio_pin_init(&pin_mosi, PA29);
// csi_gpio_pin_dir(&pin_mosi, GPIO_DIRECTION_OUTPUT);
// csi_gpio_pin_init(&pin_cs, PA27);
// csi_gpio_pin_dir(&pin_cs, GPIO_DIRECTION_OUTPUT);
// csi_gpio_pin_init(&pin_miso, PA30); //dc
// csi_gpio_pin_dir(&pin_miso, GPIO_DIRECTION_OUTPUT);
int ret= 0;
csi_pin_set_mux(PA28, PA28_SPI1_SCK);
csi_pin_set_mux(PA29, PA29_SPI1_MOSI);
csi_pin_set_mux(PA30, PA30_SPI1_MISO);
ret = csi_spi_init(&spi_handle1, 1);
if (ret < 0) {
printf("csi spi init failed\r\n");
return NULL;
}
csi_spi_mode(&spi_handle1, SPI_MASTER);
ret = csi_spi_baud(&spi_handle1, 500000);
LOGD(TAG, "#######################spi speed:%d\r\n", ret);
csi_spi_cp_format(&spi_handle1, SPI_FORMAT_CPOL0_CPHA0);
csi_spi_frame_len(&spi_handle1, SPI_FRAME_LEN_8);
csi_spi_select_slave(&spi_handle1, 1);
#ifdef SPI_USE_DMA
csi_spi_attach_callback(&spi_handle1, spi_event_cb, NULL);
csi_spi_link_dma(&spi_handle1, NULL, &spi_recv_dma);
#endif
}
</code></pre>
<p>关键就是引脚功能的打开:csi_pin_set_mux(PA28, PA28_SPI1_SCK);</p>
<p>这里需要先把引脚打开,才可以。引脚的MISO与芯片的DC相连连接</p>
<p> </p>
<p> </p>
bigbat 发表于 2021-8-30 12:46
可以中断了,但是不知为什么程序跳过了LOGD指令。
<p>应该是SPI已被OLED屏使用,所以无法输出</p>
未来开发者 发表于 2021-9-1 11:23
应该是SPI已被OLED屏使用,所以无法输出
<p>问题也已解决,目前SPI可以使用了图像正常显示。谢谢你提供的调式功能,好多问题都已解决或已知道方向了。</p>
bigbat 发表于 2021-9-1 11:54
问题也已解决,目前SPI可以使用了图像正常显示。谢谢你提供的调式功能,好多问题都已解决或已知道方向了 ...
<p>问题都出在哪些地方?</p>
littleshrimp 发表于 2021-9-2 20:40
问题都出在哪些地方?
<p>主要问题:</p>
<p>1、SPI的引脚冲突,SSD1309的MISO和DC连接,因为是单相的所以就与MISO连接了。导致初始化时冲突。</p>
<p>2、开始时无法调试,很多问题无法探测</p>
<p>3、资料缺乏API函数主要是靠例程分析</p>
页:
[1]
2