Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
AB32VG1
软件模拟spi
AB32VG1系列之软件SPI方式
发布于 2021-03-29 22:45:23 浏览:936
订阅该版
本人非常荣幸参与了中科蓝讯AB32VG1 RISC-V开发板模块的评测任务活动并成功抢到测试SPI模块的机会,在此感谢主办方给予我这次机会。 说起这块板子,中规中矩。如下图1所示,AB32VG1 RISC-V开发板实物图。  图1 AB32VG1 RISC-V开发板实物图 AB32VG1 RISC-V开发板板载硬件资源相对还是丰富的,我主要申请的测试SPI任务。翻看了AB32VG1 RISC-V reg 手册,看到里面注明是有硬件SPI功能的(不过,我没有看的太明白相关描述)。  图2 AB32VG1 reg手册 这里,我还是按照任务软件SPI来进行测试工作的,如何验证软件SPI功能,那就需要借助一个SPI接口的设备了。我使用的是1.54寸墨水屏模块来验证软件SPI功能。其连接关系如下表所示。 表1 AB32VG1开发板引脚与墨水屏模块引脚连接关系  为了保证测试工作能够顺利进行,我先对这几个引脚能否工作进行了测试。用杜邦线依次将上表中(除了PF.1)引脚与彩色LED中的LED-R引脚连接起来,然后依次用点灯程序测试,除了PA.7感觉驱动弱一点外,均可以正常工作。印象看寄存器手册时,可以设置上拉阻值的,还是没有静下心来,没有尝试更改,只是将PA.0和PA.7连接线对调了一下。 经过近2周的测试工作(这里需要说明一下,其实工作就是将墨水屏的arduino代码改写一下,我开始觉得工作难度不大,但是实际效果很差,而且没有成功驱动墨水屏,感觉很失败,稍后总结一下原因),现在将自己写的代码列出来,希望大家帮我找找问题所在(这里只贴出初始化部分,显示部分就不贴了。) ``` // Display resolution #define EPD_WIDTH 152 #define EPD_HEIGHT 152 // EPD1IN54B commands #define PANEL_SETTING 0x00 #define POWER_SETTING 0x01 #define POWER_OFF 0x02 #define POWER_OFF_SEQUENCE_SETTING 0x03 #define POWER_ON 0x04 #define POWER_ON_MEASURE 0x05 #define BOOSTER_SOFT_START 0x06 #define DEEP_SLEEP 0x07 #define DATA_START_TRANSMISSION_1 0x10 #define DATA_STOP 0x11 #define DISPLAY_REFRESH 0x12 #define DATA_START_TRANSMISSION_2 0x13 #define PLL_CONTROL 0x30 #define TEMPERATURE_SENSOR_COMMAND 0x40 #define TEMPERATURE_SENSOR_CALIBRATION 0x41 #define TEMPERATURE_SENSOR_WRITE 0x42 #define TEMPERATURE_SENSOR_READ 0x43 #define VCOM_AND_DATA_INTERVAL_SETTING 0x50 #define LOW_POWER_DETECTION 0x51 #define TCON_SETTING 0x60 #define TCON_RESOLUTION 0x61 #define SOURCE_AND_GATE_START_SETTING 0x62 #define GET_STATUS 0x71 #define AUTO_MEASURE_VCOM 0x80 #define VCOM_VALUE 0x81 #define VCM_DC_SETTING_REGISTER 0x82 #define PROGRAM_MODE 0xA0 #define ACTIVE_PROGRAM 0xA1 #define READ_OTP_DATA 0xA2 //PA0、PA1、PA2、PE4、PA6 /*--------------------引脚定义--------------------------*/ uint8_t SPI_CS;//低电平有效 uint8_t SPI_SCK; uint8_t SPI_MOSI; uint8_t SPI_MISO; uint8_t OLED_DC;//数据/命令控制引脚(高电平表示数据,低电平表示命令) uint8_t OLED_RES;//外部复位引脚(低电平复位) uint8_t OLED_BUSY ;//工作状态输出引脚(高电平表示正在工作) #define SPI_CS_HIGH rt_pin_write(SPI_CS, PIN_HIGH) #define SPI_CS_LOW rt_pin_write(SPI_CS, PIN_LOW) #define SPI_SCK_HIGH rt_pin_write(SPI_SCK, PIN_HIGH) #define SPI_SCK_LOW rt_pin_write(SPI_SCK, PIN_LOW) #define SPI_MOSI_HIGH rt_pin_write(SPI_MOSI, PIN_HIGH) #define SPI_MOSI_LOW rt_pin_write(SPI_MOSI, PIN_LOW) #define OLED_DC_HIGH rt_pin_write(OLED_DC, PIN_HIGH) #define OLED_DC_LOW rt_pin_write(OLED_DC, PIN_LOW) #define OLED_RES_HIGH rt_pin_write(OLED_RES, PIN_HIGH) #define OLED_RES_LOW rt_pin_write(OLED_RES, PIN_LOW) /*definition--------------------------------------------*/ const unsigned char lut_vcom0[] = { 0x0E, 0x14, 0x01, 0x0A, 0x06, 0x04, 0x0A, 0x0A, 0x0F, 0x03, 0x03, 0x0C, 0x06, 0x0A, 0x00 }; const unsigned char lut_w[] = { 0x0E, 0x14, 0x01, 0x0A, 0x46, 0x04, 0x8A, 0x4A, 0x0F, 0x83, 0x43, 0x0C, 0x86, 0x0A, 0x04 }; const unsigned char lut_b[] = { 0x0E, 0x14, 0x01, 0x8A, 0x06, 0x04, 0x8A, 0x4A, 0x0F, 0x83, 0x43, 0x0C, 0x06, 0x4A, 0x04 }; const unsigned char lut_g1[] = { 0x8E, 0x94, 0x01, 0x8A, 0x06, 0x04, 0x8A, 0x4A, 0x0F, 0x83, 0x43, 0x0C, 0x06, 0x0A, 0x04 }; const unsigned char lut_g2[] = { 0x8E, 0x94, 0x01, 0x8A, 0x06, 0x04, 0x8A, 0x4A, 0x0F, 0x83, 0x43, 0x0C, 0x06, 0x0A, 0x04 }; const unsigned char lut_vcom1[] = { 0x03, 0x1D, 0x01, 0x01, 0x08, 0x23, 0x37, 0x37, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const unsigned char lut_red0[] = { 0x83, 0x5D, 0x01, 0x81, 0x48, 0x23, 0x77, 0x77, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const unsigned char lut_red1[] = { 0x03, 0x1D, 0x01, 0x01, 0x08, 0x23, 0x37, 0x37, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /******************************************************************************* * 函数名称: void spi_send_byte(uint8_t value) * 函数功能: 发送8bit数据 * 函数说明: gpio模拟spi * 输入参数: * 输出参数: * 返回值 : *******************************************************************************/ void spi_send_byte(uint8_t value) { uint8_t i; uint8_t data=0; SPI_SCK_LOW; //先将时钟线拉低 for(i=0;i<8;i++) { if((value&0x80)==0x80) //从高位发送 { SPI_MOSI_HIGH; } else { SPI_MOSI_LOW; } SPI_SCK_HIGH; //将时钟线拉高,在时钟上升沿,数据发送到从设备 value<<=1; //data<<=1; //if(rt_pin_read(SPI_MISO)) //读取从设备发射的数据 //{ // data|=0x01; //} SPI_SCK_LOW; //在下降沿数据被读取到主机 } return data; //返回读取到的数据 } /******************************************************************************* * 函数名称: void spi_init(void) * 函数功能: gpio模拟spi端口初始化 * 函数说明: gpio模拟spi * 输入参数: * 输出参数: * 返回值 : *******************************************************************************/ void spi_init(void) { rt_pin_mode(SPI_CS, PIN_MODE_OUTPUT); rt_pin_mode(SPI_SCK, PIN_MODE_OUTPUT); rt_pin_mode(SPI_MOSI, PIN_MODE_OUTPUT); //rt_pin_mode(SPI_MISO, PIN_MODE_INPUT_PULLUP); rt_pin_mode(OLED_DC, PIN_MODE_OUTPUT); rt_pin_mode(OLED_RES, PIN_MODE_OUTPUT); rt_pin_mode(OLED_BUSY, PIN_MODE_INPUT); } /******************************************************************************* * 函数名称: void EPD_reset(void) * 函数功能: 复位EPD屏 * 函数说明: * 输入参数: * 输出参数: * 返回值 : *******************************************************************************/ void EPD_reset(void) { SPI_CS_HIGH; rt_thread_mdelay(200); SPI_CS_LOW; rt_thread_mdelay(200); SPI_CS_HIGH; rt_thread_mdelay(200); } /******************************************************************************* * 函数名称: void EPD_send_cmd(uint8_t cmd) * 函数功能: 向EPD屏发送命令 * 函数说明: * 输入参数: * 输出参数: * 返回值 : *******************************************************************************/ void EPD_send_cmd(uint8_t cmd) { OLED_DC_LOW; SPI_CS_LOW; spi_send_byte(cmd); SPI_CS_HIGH; } /******************************************************************************* * 函数名称: void EPD_send_data(uint8_t data) * 函数功能: 向EPD屏发送数据 * 函数说明: * 输入参数: * 输出参数: * 返回值 : *******************************************************************************/ void EPD_send_data(uint8_t data) { OLED_DC_HIGH; SPI_CS_LOW; spi_send_byte(data); SPI_CS_HIGH; } /******************************************************************************* * 函数名称: void EPD_wait_2_idle(void) * 函数功能: 等待EPD屏空闲 * 函数说明: * 输入参数: * 输出参数: * 返回值 : *******************************************************************************/ void EPD_wait_2_idle(void) { while(rt_pin_read(OLED_BUSY) == 0) { //LOW: busy, HIGH: idle rt_thread_mdelay(200); rt_kprintf("\n--ddddd'");//目前定位的问题所在,不知道是引脚问题还是协议问题,一直读取为高电平。主要手头没有示波器,无法抓取信号。另外,这种兼容arduino、树莓派方式的母排座方式,令人也不习惯。连接墨水屏,还得找公母对的杜邦线。 } } /******************************************************************************* * 函数名称: void EPD_set_lut_bw(void) * 函数功能: 将EPD屏设置黑白模式 * 函数说明: * 输入参数: * 输出参数: * 返回值 : *******************************************************************************/ void EPD_set_lut_bw(void) { uint32_t count; EPD_send_cmd(0x20); //g vcom for(count = 0; count < 15; count++) { EPD_send_data(lut_vcom0[count]); } EPD_send_cmd(0x21); //g ww -- for(count = 0; count < 15; count++) { EPD_send_data(lut_w[count]); } EPD_send_cmd(0x22); //g bw r for(count = 0; count < 15; count++) { EPD_send_data(lut_b[count]); } EPD_send_cmd(0x23); //g wb w for(count = 0; count < 15; count++) { EPD_send_data(lut_g1[count]); } EPD_send_cmd(0x24); //g bb b for(count = 0; count < 15; count++) { EPD_send_data(lut_g2[count]); } } /******************************************************************************* * 函数名称: void EPD_set_lut_r(void) * 函数功能: 将EPD屏设置红色模式 * 函数说明: * 输入参数: * 输出参数: * 返回值 : *******************************************************************************/ void EPD_set_lut_r(void) { uint32_t count; EPD_send_cmd(0x25); for(count = 0; count < 15; count++) { EPD_send_data(lut_vcom1[count]); } EPD_send_cmd(0x26); for(count = 0; count < 15; count++) { EPD_send_data(lut_red0[count]); } EPD_send_cmd(0x27); for(count = 0; count < 15; count++) { EPD_send_data(lut_red1[count]); } } /******************************************************************************* * 函数名称: void EPD_init(void) * 函数功能: 初始化EPD屏 * 函数说明: * 输入参数: * 输出参数: * 返回值 : *******************************************************************************/ uint8_t EPD_init(void) { EPD_reset(); EPD_send_cmd(POWER_SETTING); EPD_send_data(0x07); EPD_send_data(0x00); EPD_send_data(0x08); EPD_send_data(0x00); EPD_send_cmd(BOOSTER_SOFT_START); EPD_send_data(0x07); EPD_send_data(0x07); EPD_send_data(0x07); EPD_send_cmd(POWER_ON); EPD_wait_2_idle(); EPD_send_cmd(PANEL_SETTING); EPD_send_data(0x0f); EPD_send_data(0x0d); EPD_send_cmd(VCOM_AND_DATA_INTERVAL_SETTING); EPD_send_data(0xF7); EPD_send_cmd(PLL_CONTROL); EPD_send_data(0x39); EPD_send_cmd(TCON_RESOLUTION); //set x and y EPD_send_data(EPD_WIDTH & 0xff); //x EPD_send_data(EPD_HEIGHT >> 8); //y High eight EPD_send_data(EPD_HEIGHT & 0xff); //y Low eight EPD_send_cmd(VCM_DC_SETTING_REGISTER); //VCOM EPD_send_data(0x0E); EPD_set_lut_bw(); EPD_set_lut_r(); return 0; } /******************************************************************************* * 函数名称: void EPD_clear(void) * 函数功能: 清EPD屏 * 函数说明: gpio模拟spi * 输入参数: * 输出参数: * 返回值 : *******************************************************************************/ void EPD_clear(void) { uint32_t Width, Height; Width = (EPD_WIDTH % 8 == 0)? (EPD_WIDTH / 8 ): (EPD_WIDTH / 8 + 1); Height = EPD_HEIGHT; //send black data EPD_send_cmd(DATA_START_TRANSMISSION_1); for(uint32_t i = 0; i < Height; i++) { for(uint32_t i = 0; i < Width; i++) { EPD_send_data(0xFF); } } //send red data EPD_send_cmd(DATA_START_TRANSMISSION_2); for(uint32_t i = 0; i < Height; i++) { for(uint32_t i = 0; i < Width; i++) { EPD_send_data(0xFF); } } EPD_send_cmd(DISPLAY_REFRESH); EPD_wait_2_idle(); } /******************************************************************************* * 函数名称: void EPD_display(const uint8_t *blackimage, const uint8_t *redimage) * 函数功能: 显示一副图片 * 函数说明: gpio模拟spi * 输入参数: * 输出参数: * 返回值 : *******************************************************************************/ void EPD_display(const uint8_t *blackimage, const uint8_t *redimage) { uint32_t Width, Height; Width = (EPD_WIDTH % 8 == 0)? (EPD_WIDTH / 8 ): (EPD_WIDTH / 8 + 1); Height = EPD_HEIGHT; EPD_send_cmd(DATA_START_TRANSMISSION_1); for (uint32_t j = 0; j < Height; j++) { for (uint32_t i = 0; i < Width; i++) { EPD_send_data(blackimage[i + j * Width]); } } EPD_send_cmd(DATA_START_TRANSMISSION_2); for (uint32_t j = 0; j < Height; j++) { for (uint32_t i = 0; i < Width; i++) { EPD_send_data(redimage[i + j * Width]); } } //Display refresh EPD_send_cmd(DISPLAY_REFRESH); EPD_wait_2_idle(); } /******************************************************************************* * 函数名称: void EPD_sleep(void) * 函数功能: 进入睡眠模式 * 函数说明: gpio模拟spi * 输入参数: * 输出参数: * 返回值 : *******************************************************************************/ void EPD_sleep(void) { EPD_send_cmd(VCOM_AND_DATA_INTERVAL_SETTING); EPD_send_data(0x17); EPD_send_cmd(VCM_DC_SETTING_REGISTER); //to solve Vcom drop EPD_send_data(0x00); EPD_send_cmd(POWER_SETTING); //power setting EPD_send_data(0x02); //gate switch to external EPD_send_data(0x00); EPD_send_data(0x00); EPD_send_data(0x00); EPD_wait_2_idle(); EPD_send_cmd(POWER_OFF); //power off } int main(void) { uint32_t cnt = 0; uint8_t pin = rt_pin_get("PE.1"); rt_pin_mode(pin, PIN_MODE_OUTPUT); SPI_CS = rt_pin_get("PA.0");//低电平有效 SPI_SCK = rt_pin_get("PA.1"); SPI_MOSI = rt_pin_get("PF.0"); SPI_MISO = rt_pin_get("PA.7"); OLED_DC = rt_pin_get("PF.0");//数据/命令控制引脚(高电平表示数据,低电平表示命令) OLED_RES = rt_pin_get("PA.5");//外部复位引脚(低电平复位) OLED_BUSY = rt_pin_get("PF.1");//工作状态输出引脚(高电平表示正在工作) spi_init(); rt_kprintf("Reading....."); if(EPD_init()) { rt_kprintf("e-Paper init failed\r\n"); } EPD_clear(); rt_thread_mdelay(200); while (1) { if (cnt % 2 == 0) { rt_pin_write(pin, PIN_LOW); } else { rt_pin_write(pin, PIN_HIGH); } cnt++; rt_thread_mdelay(1000); } return 0; } ``` 希望有大侠帮我释疑,或提出解决方案。 下来谈谈我的使用感受:从硬件角度说,AB32VG1开发板功能还是非常强大,我目前还只是触摸一下冰山的一角,相信其强大的功能会在今后项目中发挥出来。但测试过程中由于中科蓝讯方没有提供X_LINK模块功能(开发板原理图上看到此模块,虽然不知道它具有哪些功能,但从名字看,应该功能不必J_LINK差吧。)令我感到非常遗憾,以及在测试工作中感到非常痛苦,让我不停的在RT Studio IDE、downloader和串口putty间来回切换,导致工作效率非常低下。如果AB32VG1开发板能支持像J-Link在IDE环境中单步调试、查看var等功能,那么相信基于该板子的开发工作会更高的,也能更好的定位问题所在。
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
mabo124
这家伙很懒,什么也没写!
文章
1
回答
1
被采纳
0
关注TA
发私信
相关文章
1
riscv32-elf-xmaker 工具的目的
2
AB32VG1 的 RTC 内部怎么知道自己是第一次上电的呢?
3
AB32VG1 蓝牙功能
4
AB32VG1 片上 flash 的库能否发布出来
5
【中科蓝汛AB32VG1】开发板是否支持USB HOST
6
有基于RT-Thread 和 AB32VG1 的蓝牙示例吗?
7
AB32VG1_RTC时钟
8
AB32 串口2.是哪个管脚
9
AB32VG1开发板的三路LPWM使用
10
使用RT-thread新建AB32VG1工程编译时报错
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
rt-smart
FAL
I2C_IIC
UART
ESP8266
cubemx
WIZnet_W5500
ota在线升级
PWM
BSP
flash
freemodbus
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
编译报错
socket
中断
Debug
rt_mq_消息队列_msg_queue
keil_MDK
ulog
SFUD
msh
C++_cpp
MicroPython
本月问答贡献
RTT_逍遥
10
个答案
3
次被采纳
xiaorui
3
个答案
3
次被采纳
踩姑娘的小蘑菇
6
个答案
2
次被采纳
winfeng
2
个答案
2
次被采纳
KunYi
9
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
lizimu
2
篇文章
9
次点赞
jinchanchan
2
篇文章
2
次点赞
alight
1
篇文章
5
次点赞
swet123
1
篇文章
4
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部