Num1:首先要来了解I2C接口。
aduc7023I2C接口不同于51单片机的模拟出来的I2C。只要对ADuc7023相应的I2C寄存器进行操作即可。它类似于UART,具有2字节的FIFO。在未写入从地址之前,传输并未开始。
OUT和IN是从机自动进行操作的。
主机发送:
在发送字节前,必须首先将数据载入发送FIFO,即I2C0MTX中。I2C0ADR寄存器中必须指定从机的地址。对于数据写入,地址寄存器中的写操作(W)位必须置0。写入I2C0ADR寄存器会自动产生一个起始条件,并启动传输。(注意是自动产生起始条件的,而且只有写入I2C0ADR之后才能启动)
每个发送字节的第一个时钟脉冲上会产生一个I2C中断。I2C0MSTA的位2和位1置1,表示主机刚刚发送一个字节,并且FIFO下溢。因此,用户可以向FIFO添加一个字节。
如果启动传输时FIFO中只有一个字节,则第一个I2C中断发生在所发送地址的第一个时钟脉冲上。如果FIFO中有两个字节,则中断发生在所发送的第一个字节的第一个时钟脉冲上。(即启动传输时FIFO中得有字节,一个或两个都可以,在写入I2C0ADR寄存器之前写I2C0MTX。传输开始时,第一个字节将触发中断)
主机接收:
通过I2C0CNT寄存器配置要读取的字节数。其值表示要从从机读取的字节数加1。(当读取够I2C0CNT配置的字节数时主机不再接收更多数据,通知从机停止传输字节,不再产生中断 重要!!!!!!)
为了开始接收数据,I2C0ADR寄存器中的读操作(R)位应置1。这将启动传输,并利用I2C0ADR寄存器所设置的地址和R/W位产生起始条件。接收到每个字节后(第9个时钟脉冲ACK或NACK之后),会产生一个中断。I2C0MSTA的位3置1,表示刚刚接收到一个字节。只有读取I2C0MRX才能使此位清零。
当主机不需要接收更多数据时(即满足I2C0CNT配置的字节数,I2C0CNT是内置的计数器,自动对读取的字节数计数,达到时停止接收字节),它针对最后接收到的字节自动产生NACK。这相当于通知从机停止传输字节,以便主机能够产生停止条件。
如果没有及时读取所接收到的数据,并且FIFO已满,则主机将针对所接收到的额外数据提供一个NACK。
发送和接收触发中断的条件(首先要使能IRQEN对应的I2Cx位,比如第10位置1使能I2C1中断):
接收:启动传输后等待从机发送数据,当数据进入接收FIFO后,即产生中断
发送:启动传输后,当主机完成一个字节传输时,产生中断
产生中断以后,开始对于中断的处理:
aduc7023 读取IRQSTA判断是否是I2C1主机产生的中断,如果是,则再读取I2CxMSTA判断是接收请求中断还是发送请求中断。
若是接收请求中断,则判断有没有够接收字节数(可以少于I20CNT,但不能多于I2C0CNT),如果还需要接收,则继续读取I2C1MRX;当达到I2C0CNT时不再接收字节,不再产生中断。
若是发送请求中断,则判断发送的字节数有没有达到要求的字节数,是否要继续发送(多发送一位空的//错误,不需要多发送一位,如果是字符串,用sizeof(),自己会发送末尾的'\0'的 \\事后再实验发现这个结论也是错的,想不明白。。 )
(一)I2C操作
①初始化:
1.选择管脚功能为I2C功能(此I2C对应的管脚要看原理图中所连的管脚,比如scl1,sda1)
2.设置I2C时钟频率(PLLCON控制时钟系统的工作模式,POWCON0控制内核时钟频率和掉电模式,这是系统初始化要用到的,而POWCON1则控制I2C和SPI的时钟频率。为了防止意外编程,写PLLCON和POWCONx寄存器时需要遵循特定的时序。),即设置POWCON1。
所以一般配置为POWKEY3=0X76;POWCON1=0X124;(将2,5,8位置1,SPI,I2C时钟为41.78MHZ)POWKEY4=0XB1;
3.设置串行时钟频率:I2CxDIV
一般选择100KHZ,即设置为I2CxDIV=0XCFCF;
4.使能中断IRQEN(由于使用到了中断,当中断使能时,接收或发送都会触发中断,具体每一位代表什么可参考相应datasheet)
②主机发送操作
(具体参考AN895应用笔记,这个是ADuc702x系列,略有不同,但过程大同小异)
1.Flush TX FIFO
2.向TX FIFO中写入一字节(或两字节,根据前文发送FIFO操作中所要求的,反正传输开始时第一个字节发送出OUT就会产生中断)
3.写I2CxADR0从机地址(读写位设为写 启动传输,等待第一个字节发送出去产生中断)
4.等待要求字节数的数据传送完毕(进入IRQ服务程序,判断是否还有数据需要发送,若有继续发送到TX FIFO中
③主机接收操作
根据上图要求,读取数据前就需要设置I2CxMCNT0(内置计数器,达到以后不再读取数据)
1.设置I2CxMCNT0
2.写I2CxDAR0(读写位设置为读 传输开始等待,等待IN传给RX FIFO中,有数据传入则产生中断 ; 读数据指的是读SC16IS740芯片寄存器中的数据,如读RHR寄存器中的数据)
3.等待要求的字节数的数据读出完毕(读的字节数可以少于I2CxMCNT0,此时因为没有及时读取所接收到的数据,若FIFO已满,则主机将针对所接收到的额外数据提供一个NACK,以停止传输,若FIFO不满,则继续传输。注意FIFO只有2字节)
Num2:uart操作(可以就把SC16IS740当作aduc7023的一部分,uart的寄存器在SC16IS740里,需要用I2C通信来读取或写相应uart寄存器地址处的值)
uart初始化:
①设置波特率。打开除数锁存端,配置DLL,DLH,配置完成后关闭除数锁存端
②选择数据格式。
③设置触发深度FIFO,并复位TX FIFO,RX FIFO,使能FIFO(当UART接收到大量字符且这些数据不足够以触发接收中断(因为它们没有到达接收触发点)时,UART将在接收到最后一个字符后4字符时间内产生超时中断。超时中断也能触发uart的IRQ,它是SC16IS740上的IRQ。超时计数器将在接收到的每个停止位的中间或每次读接收FIFO时复位。)
④使能中断IEREN
所以uart内部寄存器要左移三位再写入
写寄存器操作(往相应寄存器地址处写字节即可设置,寄存器地址按上图规定左移三位):
①Flush TX FIFO
②写一字节到TX FIFO I2C1MTX=reg;
③写从地址 I2C1ADR0=从地址(读写位为写),启动传输,然后会传输reg.
④判断数据是否传完(对于普通寄存器设置来说,接下来只要再传输一字节即可,对于THR则可能传输多个字节,按照上图来)
读寄存器操作(按照上图,操作时序为从地址(写)->reg->从地址(读)->数据,读出的数据要另外定义一个变量用于存放)
①I2C写操作,写reg(就是写一个寄存器地址)
②I2C读操作,读出数据存放。
接收器、发送器:
①接收保存寄存器(RHR)
接收器部分由一个接收保存寄存器(RHR)和接收移位寄存器(RSR)组成。RHR实际上是一个64字节FIFO。RSR接收RX端的串行数据。然后将数据转化为并行数据并转移到RHR。线控制寄存器控制接收器部分。如果FIFO被禁能,则FIFO的单元0用来存储字符。
②发送保存寄存器(THR)
发送器部分由一个发送保存寄存器(THR)和发送移位寄存器(TSR)组成。THR实际上是一个64字节FIFO。THR接收数据并将其移入TSR。然后在TSR中将其转化为串行数据并在TX端移出。如果FIFO被禁能,则FIFO仍用来存储字节。如果发生溢出则字符丢失。(THR接收数据就是在THR地址处写多个字节)
UartsendBytes操作:
I2C写操作,往THR地址中写n个字节(都存放到了该64字节FIFO中),等待终端读光FIFO
UartreadBytes操作(由于未使用中断服务程序来读取,所以与触发深度无关):
I2C读操作,读取LSR状态,通过LSR[0]判断RX FIFO中是否有数据,若有,则循环I2C读取RXLVL判断有多少字符,并通过I2C读取RHR寄存器字符,直到RXLVL没有字符数