基于ARM板s3c2440---SPI协议

发布者:chinalisa最新更新时间:2022-04-20 来源: eefocus关键字:ARM板  s3c2440  SPI协议 手机看文章 扫描二维码
随时随地手机看文章

SPI简介

SPI是串行外设接口(Serial Peripheral Interface)的缩写。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,如今越来越多的芯片集成了这种通信协议,比如AT91RM9200。

简单的说,就是SPI是一种告诉的协议,相当于IIC,只是IIC是两根线(时钟线SCL,数据地址线SDA)而SPI是四根线(SCK时钟信号,DO输出线,DI输入线,CSn片选信号),同样可以挂在多个SPI高速设备。

在这里插入图片描述

数据传输

在这里插入图片描述

数据传输由CPOL,CPHA两个控制器决定,CPOL决定电平启示状态是低电平还是高电平,CPHA决定在第一个沿采样还是第二个沿采样

在这里插入图片描述

通过SPI协议实现对OLED屏幕的显示

在这里插入图片描述

OLED显示原理

在这里插入图片描述

屏幕分辨率是12864,如同LCD一样,我们需要一个显存来存放数据,这个显存在内存中开辟,一个字节八位,分别表示该列元素的亮(1)或者灭(0)

在这里插入图片描述
在这里插入图片描述

按168的大小在屏幕上显示,一行为一个page,在光标移动到底8列时,光标归为0,page+1,实现第二个page的写操作


通过GPIO模拟SPI的数据收发

在这里插入图片描述

原理图中使用到GPG3567和GPF1,所以需要设置S3C2440相应的管脚的输入输出模式,除开GPG5为输入模式,其余管脚都是输出模式。

在这里插入图片描述
在这里插入图片描述

static void SPI_GPIO_INIT(void)

{

    /*GPF1 OLED_CSn OUTPUT*/    /*主机是输出模式*/

    GPFCON &= ~(3<<2);

    GPFCON |= (1<<2);

    GPFDAT |= (1<<1);    /*因为接了OLED 和 FLASH  如果同时为0  会产生冲突*/

    /*GPG2 FLASH_CSn  OUTPUT*/

    /*GPG4 OLED_DC OUTPUT*/

    /*GPG5 SPIMISO INPUT*/    /*MI:MASTER INPUT*/

    /*GPG6 SPIMOSI OUTPUT*/

    /*GPG7 SPICLK OUTPUT*/

    GPGCON &= ~((3<<4)|(3<<8)|(3<<12)|(3<<14)|(3<<10));

    GPGCON |= ((1<<4)|(1<<8)|(1<<12)|(1<<14));

    GPGDAT |=(1<<2);    /*因为接了OLED 和 FLASH  如果同时为0  会产生冲突*/

                        /*CSn低电平有效*/

                        /*都不片选,使其在使用时裁片选*/

}


由于芯片上接入了FLASH和oled的片选信号,所以在GPIO的初始化时,需要将两个片选信号都拉高,避免默认状态冲突。


OLED初始化

void oledinit(void)

{

    /*向OLED发命令初始化*/

    /*SPEC UG手册提供的初始化命令*/

    OLEDWriteCmd(0xAE); /*display off*/ 

    OLEDWriteCmd(0x00); /*set lower column address*/ 

    OLEDWriteCmd(0x10); /*set higher column address*/ 

    OLEDWriteCmd(0x40); /*set display start line*/ 

    OLEDWriteCmd(0xB0); /*set page address*/ 

    OLEDWriteCmd(0x81); /*contract control*/ 

    OLEDWriteCmd(0x66); /*128*/ 

    OLEDWriteCmd(0xA1); /*set segment remap*/ 

    OLEDWriteCmd(0xA6); /*normal / reverse*/ 

    OLEDWriteCmd(0xA8); /*multiplex ratio*/ 

    OLEDWriteCmd(0x3F); /*duty = 1/64*/ 

    OLEDWriteCmd(0xC8); /*Com scan direction*/ 

    OLEDWriteCmd(0xD3); /*set display offset*/ 

    OLEDWriteCmd(0x00); 

    OLEDWriteCmd(0xD5); /*set osc division*/ 

    OLEDWriteCmd(0x80); 

    OLEDWriteCmd(0xD9); /*set pre-charge period*/ 

    OLEDWriteCmd(0x1f); 

    OLEDWriteCmd(0xDA); /*set COM pins*/ 

    OLEDWriteCmd(0x12); 

    OLEDWriteCmd(0xdb); /*set vcomh*/ 

    OLEDWriteCmd(0x30); 

    OLEDWriteCmd(0x8d); /*set charge pump enable*/ 

    OLEDWriteCmd(0x14);


    OLEDPAGEADDRMODE();

    OLEDCLEAR();

    OLEDWriteCmd(0xAF); /*display ON*/

}


在OLED初始中实现对地址采用Page address mode

在这里插入图片描述

static void OLEDPAGEADDRMODE(void)

{

    OLEDWriteCmd(0x20);

    OLEDWriteCmd(0x02);

}


清屏幕


static void OLEDCLEAR(void)

{

    int page,col,i;

    for(page = 0; page <8;page++)

    {

        OLEDSETPOS(page,0);

        for(i=0;i<128;i++)

        {

            OLEDWriteDAT(0);

        }

    }

}


地址/数据模式

OLED_DC:高电平表示数据,低电平表示数据。


/*命令*/

static void OLEDWriteCmd(unsigned int cmd)

{

    OLED_SET_DC(0); /*COMMAND*/

    OLED_SET_CS(0); /*选中OLED*/


    SPISENDBYTE(cmd);


    OLED_SET_CS(1); /*取消选中OLED*/

    OLED_SET_DC(1); /*COMMAND*/

}

/*地址*/

static void OLEDWriteDAT(unsigned int dat)

{

    OLED_SET_DC(1); /*data*/

    OLED_SET_CS(0); /*选中OLED*/


    SPISENDBYTE(dat);

    

    OLED_SET_CS(1); /*取消选中OLED*/

    OLED_SET_DC(1); /*data*/

}


根据传入0/1设置相应的GPIO口输出高低电平


static void OLED_SET_DC(char val)

{

    if(val)

    {

        GPGDAT |= (1<<4);

    }

    else

    {

        GPGDAT &= ~(1<<4);

    }

    

}


片选信号


static void OLED_SET_CS(char val)

{

    if(val)

    {

        GPFDAT |= (1<<1);

    }

    else

    {

        GPFDAT &= ~(1<<1);

    }

    

}


数据传输


void SPISENDBYTE(unsigned char val)

{

    int i;


    for(i=0;i<8;i++)

    {

        SPI_SET_CLK(0);

        SPI_SET_DO(val & 0x80);

        SPI_SET_CLK(1);

        val <<= 1;

    }

}


时钟设置


static void SPI_SET_CLK(char val)

{

    if(val)

    {

        GPGDAT |= (1<<7);

    }

    else

    {

        GPGDAT &= ~(1<<7);

    }

    

}


数据输出--------按位传递,熊高位到低位


static void SPI_SET_DO(char val)

{

    if(val)

    {

        GPGDAT |= (1<<6);

    }

    else

    {

        GPGDAT &= ~(1<<6);

    }

    

}


程序到这里已经实现了CPU的数据传出,接下来需要将数据收到,以及打印到OLED的相应位置


void oledprint(int page,int col,char *str)

{

    int i = 0;

    while(str[i])

    {

        OLEDPUTCHAR(page,col,str[i]);

        col += 8;

        if(col > 127)

        {

            page += 2;

            col = 0;

        }

        i++;

    }

}


一个字节占8列,16行(16*8)

在这里插入图片描述

void OLEDPUTCHAR(int page,int col,char c)

{

    int i=0;

    /*字摸*/

    const unsigned char *dots = oled_asc2_8x16[c - ' '];

    /*发给OLED*/

    OLEDSETPOS(page,col);

    /*发出8字节数据*/

    for(i=0;i<8;i++)

    {

        OLEDWriteDAT(dots[i]);

    }

    OLEDSETPOS(page+1,col);

    /*发出8字节数据*/

    for(i=0;i<8;i++)

    {

        OLEDWriteDAT(dots[i+8]);    /*原因是字符数组二维数组是16个为一组,前8个是上一排的,后8个是下一排*/

    }

}

在这里插入图片描述

static void OLEDSETPOS(int page, int col)

{

    OLEDWriteCmd(0xb0 + page);      /*page address*/


    OLEDWriteCmd(col & 0xf);        /*Set Lower Column Start Address for Page Addressing Mode*/

    OLEDWriteCmd(0x10 +(col>>4));   /*Set Higher Column Start Address for Page Addressing Mode*/

}


通过SPI协议实现对FLASH的操作

读厂家ID、设备ID

在这里插入图片描述

首先发送0x90,然后发出3个字节的0(是一个24位的数据,所以需要分割为3个字节来发送),然后GPG5就有数据读入。


void SPIflashreadID(int *pMID,int *pDID)

{

    SPI_FLASH_set_cs(0);    /*选中SPIflash*/


    SPISENDBYTE(0X90);

    SPIFlashSendAddr(0);      /*当发完这些指令和地址是,GPGDAT5上就有数据传入*/

    *pMID = SPIRecvByte();

    *pDID = SPIRecvByte();

    SPI_FLASH_set_cs(1);    /*取消选中SPIflash*/

}


static void SPIFlashSendAddr(unsigned int addr)

{

    SPISENDBYTE(addr>>16);      /*地址由24位组成,先发高高8位*/

    SPISENDBYTE((addr>>8)&0xff);      /*地址由24位组成,再发高8位*/

    SPISENDBYTE(addr&0xff);      /*地址由24位组成,最后发低8位*/


}


static void SPI_FLASH_set_cs(char val)

{

    if(val)

    {

        GPGDAT |= (1<<2);       /*不选中*/

    }

    else

    {

        GPGDAT &= ~(1<<2);      /*选中*/

    }

    

}


/*主机传入*/

static char SPI_SET_DI(void)

{

    /*需要判定GPGDAT第5位是什么数据*/

    if(GPGDAT &(1<<5))

    {

        return 1;

    }

    else

    {

        return 0;

    }

}

unsigned char SPIRecvByte(void)

{

    int i;

    unsigned char val = 0;  /*用于存放本字节的东西*/

    for(i=0;i<8;i++)

    {

        val <<= 1;

        SPI_SET_CLK(0);

        if(SPI_SET_DI())

        {   

            val |= 1;       /*数据为1就或1,否则就是0,前面左移已经产生了,所以不用赋值*/

        }

        SPI_SET_CLK(1);

    }

    return val;

}


对FLASH进行读写

在这里插入图片描述

对FLASH的写操作,需先进进行写使能,取出状态寄存器的保护,然后擦除,然后写入

写使能:

在这里插入图片描述

写保护:

在这里插入图片描述

static void SPIFlashWriteEnable(int enable)

{

    if (enable)

    {

        SPI_FLASH_set_cs(0);

        SPISENDBYTE(0x06);

        SPI_FLASH_set_cs(1);

    }

    else

    {

        SPI_FLASH_set_cs(0);

        SPISENDBYTE(0x04);

        SPI_FLASH_set_cs(1);

    }

}


读状态寄存器

在这里插入图片描述

发送0x05命令,接下来就可以读数据了


static unsigned char SPIFlashReadStatusReg1(void)

{

    unsigned char val;

    SPI_FLASH_set_cs(0);

    SPISENDBYTE(0x05);

    val = SPIRecvByte();

    SPI_FLASH_set_cs(1);

    return val;

}

static unsigned char SPIFlashReadStatusReg2(void)

{

    unsigned char val;

    SPI_FLASH_set_cs(0);

    SPISENDBYTE(0x35);

    val = SPIRecvByte();

    SPI_FLASH_set_cs(1);

    return val;

}


写状态寄存器


static void SPIFlashWriteStatusReg(unsigned char reg1, unsigned char reg2)

{    

[1] [2]
关键字:ARM板  s3c2440  SPI协议 引用地址:基于ARM板s3c2440---SPI协议

上一篇:用openocd+jtag并口小板调试qq2440
下一篇:十四、S3C2440 裸机 — MMU

推荐阅读最新更新时间:2024-11-09 11:16

ARM+FPGA开发的强劲图形系统体验——米尔基于NXP i.MX 8M Mini+Artix-7开发
ARM+FPGA开发板的强劲图形系统体验——米尔基于NXP i.MX 8M Mini+Artix-7开发板 关键词:NXP、Xilinx、i.MX 8M Mini、Artix-7、ARM+FPGA、图像处理、异构处理器 本篇测评由优秀测评者“qinyunti”提供。 01 ARM+FPGA异核架构开发板简单介绍 MYD-JX8MMA7的这款ARM+FPGA异核架构开发板, 拥有2个GPU核,一个用来做3D数据处理,另一个用来做2D和 3D加速。3D GPU核支持:  OpenGL ES 1.1,2.0  Open VG 1.1  2D GPU核支持  多图层混合 基于ARM+FPG
[嵌入式]
<font color='red'>ARM</font>+FPGA开发<font color='red'>板</font>的强劲图形系统体验——米尔基于NXP i.MX 8M Mini+Artix-7开发<font color='red'>板</font>
s3c2440裸机-LCD编程(三、框架准备和LCD初始化)
1.准备框架 为了让程序更加好扩展,体现出”高内聚、低耦合 的特点,能够兼容各种不同型号的lcd,假如有两款尺寸大小的lcd,如何快速的在两个lcd上切换? 首先我们抽象出lcd_3.5.c和lcd_4.3.c的共同点,比如都有初始化函数init(),我们可以新建一个lcd.c,然后定义一个结构体: struct lcd_opr{ void (*init)(void); }; 用户不接触lcd_3.5.c和lcd_4.3.c,只需要在lcd.c里通过指针访问对应的结构体的函数,也就调用了不同init(),如下图所示: 我们的目的是在LCD显示屏上画线、画圆(geomentry.c)和写字(font.c)其核心是画点
[单片机]
<font color='red'>s3c2440</font>裸机-LCD编程(三、框架准备和LCD初始化)
S3C2440看门狗定时器原理
  看门狗定时器(Watchdog)   相信大家都看过中国移动前些时间做的一个广告,从城市到山村,到青藏高原,在哪儿都有中国移动的网络,到哪儿都能打电话,由此可以联想到中国移动在全国有无数个信号基站,很多基站建设在环境比较恶劣的地方,我们来思考一个问题?假如,有一天某个基站出了问题不能正常工作了,毫无疑问,移动的工作人员会带各种检测设备去进行修理,如果是出现非硬件故障(如用户电话服务突然巨增,造成繁忙死机或电磁干扰造成CPU运行出错等),导致基站服务器出现异常死机,工作人员只需要进行一个操作,重启一下即可。如果该基站安装在青藏高原上,这样一次上去,成本是很大的。退一步讲,这种情况虽然成本很高,但是还是可以修复的,如果这种情况出现
[单片机]
<font color='red'>S3C2440</font>看门狗定时器原理
12-S3C2440驱动学习(九)嵌入式linux-USB驱动程序(未完待续)
1、学习思路 一个USB设备插入到系统中时,会被系统识别出USB设备,并通过系统上的USB总线驱动程序通过约定好的规范询问USB设备的信息(描述符),如设备名称。USB总线驱动程序负责:识别USB设备,给USB设备找到对应的驱动程序(自己开发)。USB设备通过约定好的规范,把描述符发送给USB总线驱动程序。 问1. 既然还没有 驱动程序 ,为何能知道是 android phone 答1. windows里已经有了USB的总线驱动程序,接入USB设备后,是 总线驱动程序 知道你是 android phone ,提示你安装的是 设备驱动程序 。 问2. USB设备种类非常多,为什么一接入电脑,就能识别出来? 答2.
[单片机]
12-S3C2440驱动学习(九)嵌入式linux-USB驱动程序(未完待续)
基于S3C2440和DM9000移植LWIP(一)
使用mini2440已经有一段时间了。诸如裸机的LED,键盘开关等等等等也都试验过了,uCOS,WinCE也是浅尝了一下。如今想到了以太网。 由于mini2440的板上集成了一个DM9000的网卡,并且在CE系统里面成功的使用以太网与PC连接了。于是自然而然的想,能不能在uCOS下也实现以太网接口呢? 一上来什么都不懂,于是找一些资料,在这里要谢谢焦海波老师所著的嵌入式网络系统设计一书,移植过程中很多资料都来源于这本书。其次是mikenoodle的单片机驱动DM9000网卡一文,里面详细地讲述如何在2440裸机下驱动DM9000网卡。 首先明确我们需要做的事情是什么?为了实现在uCOS下的LWIP协议。我们当然需要一个LWIP协议
[单片机]
s3c2440中断总结+按键中断
一、启动代码之IRQ中断分析。 举例:timer4中断调用过程 1、当timer4发生中断,INTOFFSET寄存器的值变为中断源INT_TIMER4对应的值,即 14。 同时,程序将跳转到irq中断向量地址(0x18)处去执行,该处的指令为 b HandlerIRQ 2、在启动代码中有如下一段宏定义 $HandlerLabel HANDLER $HandleLabel $HandlerLabel sub sp,sp,#4 ;decrement sp(to store jump address) stmfd sp!,{r0} ;PUSH the work register to stack(lr does
[单片机]
<font color='red'>s3c2440</font>中断总结+按键中断
/sys/class/gpio 文件接口操作IO端口(s3c2440)
在嵌入式设备中对GPIO的操作是最基本的操作。一般的做法是写一个单独驱动程序,网上大多数的例子都是这样的。其实Linux下面有一个通用的GPIO操作接口,那就是我要介绍的 “/sys/class/gpio” 方式。 首先,看看系统中有没有“/sys/class/gpio”这个文件夹。如果没有请在编译内核的时候加入 Device Drivers — GPIO Support — /sys/class/gpio/… (sysfs interface)。 /sys/class/gpio 的使用说明: 01 gpio_operation 通过/sys/文件接口操作IO端口 GPIO到文件系统的映射 class/gpio c
[单片机]
s3c2440 移值u-boot-2016.03 第5篇 支持dm9000 识别
1, 通过查看 /drivers/net/Makefile 发现想要编译上,需要添加宏 /include/configs/smdk2440.h 中添加 #define CONFIG_DRIVER_DM9000 #define CONFIG_DM9000_BASE 0x20000000 #define DM9000_IO CONFIG_DM9000_BASE #define DM9000_DATA (CONFIG_DM9000_BASE+4) #define CONFIG_NETMASK 255.255.255.0 #define CONFIG_IPADDR 192.168.1.123 #define CONFIG_SERVE
[单片机]
<font color='red'>s3c2440</font> 移值u-boot-2016.03 第5篇 支持dm9000 识别

推荐帖子

MSP MCU I2C入门指南
I2C(或称为I2C,集成电路总线)是一种两线制通信形式,主要用来在短距离、电路板间的应用中,实现微控制器与外设IC之间的低速通信。由于其采用范围很广,所以学习使用I2C与MSPMCU之间的通信已经在帮助工程师开发应用方面变得十分必要。通过使用一个超低功耗MSPMCU来访问和控制IC器件,这份指南提供了理解I2C协议并执行这一协议所需的工具与资源。器件术语驱动SCL时钟线路的器件被称为主器件,而对其进行响应的器件被称为从器件。在大多数应用中,MSPMCU为主器
Jacktang DSP 与 ARM 处理器
SWD无法下载,请问什么原因啊??
JLinkinfo:------------DLL:V6.30h,compiledMar16201818:02:51Firmware:J-LinkV9compiledMar2201817:07:57Hardware:V9.40S/N:59425868Feature(s):RDI,GDB,FlashDL,FlashBP,JFlash,RDDI*JLinkInfo:STM32(connect):Cannotattach
wdliming stm32/stm8
如何将U盘的物理(扇区)地址对应上盘符(windows OS)
我最近在做U盘分区,通过修改U盘主引导记录的分区表(DPT),可以将U盘分为1个以上的分区。修改DPT、格式化之后,系统只识别第一个分区。尽管我通过winhex将后面分区的DBR修改到和可识别分区的DBR一致,在windows系统的“计算机管理/磁盘管理”中也可以看到U盘中的新分区,并且显示状态良好,但就是无法格式化,也无法分配盘符。请问如何给U盘的新分区分配一个盘符?或者是将新增加的盘符映射到新分区中(通过指定U盘扇区的方式)?急!在线等!谢谢!如何将U盘的物理(扇区)地址对应上盘符
蒙蒙静 嵌入式系统
求msp430f2274使用内部AD读取正弦波的例程
求msp430f2274使用内部AD读取正弦波的例程,最好能有读取波形然后存储在MEM中再原样输出的例程,谢谢,自己弄了一个星期了没出来求msp430f2274使用内部AD读取正弦波的例程2274是10位ADC回复楼主fanfan1308的帖子楼主可以贴一些自己尝试过的程序。遇到哪些问题没解决的也标注下。方便别人帮忙解决有没有呀,求教导,求探讨,求分享回复板凳孤独剑的帖子#includemsp430x22x4.hunsignedintad_value;
fanfan1308 微控制器 MCU
来看看老外搞的廉价冲锂电线路!
老外也喜欢便宜货啊!500){this.resized=true;this.width=500;this.alt=\'这是一张缩略图,点击可放大。\\n按住CTRL,滚动鼠标滚轮可自由缩放\';this.style.cursor=\'hand\'}\">500){this.resized=true;this.width=500;this.alt=\'这是一张缩略图,点击可放大。\\n按住CTRL,滚动鼠标滚轮可自由缩放\';this.style.cursor=\'hand\'
zbz0529 电源技术
肖特基二极管应用注意事项有哪些?
肖特基二极管由于其快速开关速度和低正向压降,广泛应用于电源管理、射频和通讯设备等领域。然而,在使用肖特基二极管时,工程师需要注意一些关键的应用事项,以确保器件在电路中可靠运行,并最大化其性能优势。以下是几项重要的应用注意事项:1.正向电压降和功耗管理肖特基二极管的低正向压降是其主要优点之一,这意味着它在导通状态下损耗较小,适用于高效电源管理应用。然而,即便是较低的正向电压降,在高电流应用中也可能导致显著的功率损耗。为此,需要注意以下几点:选择合适的肖特基二极管:根据电路中的电流大小选择合
辰达行电子 玄铁RISC-V活动专区
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved