|
CSI其实是项目中比较关键的地方,一来无线模块就是SPI的,而12864虽然没说,但看起来时序也是SPI的,如果两个共用,那还是比较省IO口的。
瑞萨的CSI和典型的四线SPI比少了一根CSN这个脚,需要用是用普通IO来做,并没有并到CSI本身的功能中去,其实这是个很实用的特性。另外剩下的三个脚,瑞萨的名字有点不一样,除了SCK,SI表示data IN,SO表示data OUT,而一般的主SPI,MOSI或者简写为SI表示data out,而MISIO或者简写SO表示data in,这个要注意。在瑞萨官方的application note里面提供了807的CSI master代码,其实807和809的CSI是完全一样的,拿来改一下单片机,就可以运行的,可以参考学习。觉得代码写的还是不错的。
同时硬件上要注意的是电位器正好在SI00的位置,所以要打到最高电压,免得通信不正常。下面来看CSI的配置。
CSI是SAU0的一部分,SAU0有2个通道,每个通道都可用做UART0(注意,这并不是说,可以有两个UART),但只有第一个通道可以用做CSI00。所以如果要同时用UART,就只能放第二个通道了。CSI00工作过程如下:
使能SAU0,:SAU0EN = 1U;这个要等待一会儿,等时钟稳定。然后设定工作时钟源:SPS0,分为上下两段,可以控制两路SCK的频率。0x00表示不分频,0xff表示2^15分频!!。出来的分别为CK01和CK00。然后就开始CSI的初始化了,可见UART的最初也是这个。可以把CK01设成高频,供CSI使用,CK00低一点,供UART使用。
- void SAU0_Create(void)
- {
- SAU0EN = 1U; /* supply SAU0 clock */
- NOP();
- NOP();
- NOP();
- NOP();
- SPS0 = 0x00U;
- CSI00_Create();
- }
复制代码
然后是初始化:分为以下过程:
停止通道:ST0 |=0x01(这一步是必须的,因为运行时不能指定SMR、SDR和SCR。启用MK,clearIF,清除出错位标记。
指定中断优先级:CSIPR100和CSIPR000,一般使用默认11
然后是关键的三个:SMR,SCR和SDR。每个寄存器都有H和L,共16bit。
SMR00H:只用到bit7,选择时钟CK1或者CK0;bit6,主从选择,0 for master,1 for slave,master的运行时钟还要继续分频,参考SDR00H。所以啊,SMR00H=0x00。
SMR00L:只用到末两位,可以使用默认值0x20;2代表CSI模式。
SCR00H:bit7和6控制收发使能,要变成11,bit5和4控制CSI类型,一般都是用类型1,00。后4位在CSI中必须用0,所以SCR00H=0xC0;(注意了,看了CSI和SPI的时序比较,发现瑞萨不按常理出牌,SPI类型1要用CSI类型4,11,所以SCR00H=0xF0);
SCR00L:bit7使用0,MSB;bit0用1,8位数据。复位值0x87给UART用的(LSB),CSI使用0x07;
SDR00H:不要被名字迷惑,这个不是放data的,是用来放工作时钟的分频系数的,例子中用了3E,64分频,但是实际用0就可以,2分频,因为24L01可以使用10M,不过啊,LCD似乎不行啊。。。。
SDR00L是收发缓冲寄存器,不用设定,不放心的可以清零。注意哦,在CSI中,使用了SIO00这个代号来代表SDR00L,我晕啊!
接下来设定时钟和data 口的初始电平:CKO0和SO0,控制位在最后一位。CKO0和SCR00H中设置的类型有关,必须参考从设备的时序。现在用类型4,所以CKO0=0;SO0关系不大。
最后是SOE0,使能CSI输出。也是最后一位。
其他IO设置就随便看看,这个函数可以直接复制。我这里用的就是官方807代码
- void CSI00_Create(void)
- {
- ST0 |= 0x01U; /* disable CSI00 */
- CSIMK00 = 1U; /* disable INTCSI00 interrupt */
- CSIIF00 = 0U; /* clear INTCSI00 interrupt flag */
- /* Set INTCSI00 low priority */
- CSIPR100 = 1U;
- CSIPR000 = 1U;
- SIR00 = 0x03U; /* clear error flag */
- SMR00H = 0x00U;
- SMR00L = 0x20U;
- SCR00H = 0xF0U; //FF for SPI mode 0
- SCR00L = 0x07U;
- SDR00H = 0x3EU;
- SDR00L = 0x00U;
- CKO0 =0;//|= 0x01U; /* CSI00 clock initial level */
- SO0 &= (uint8_t)~0x01U; /* CSI00 SO initial level */
- SOE0 |= 0x01U; /* enable CSI00 output */
- /* Set SI00 pin */
- PMC0 &= 0x7FU;
- PM0 |= 0x80U;
- /* Set SO00 pin */
- P0 |= 0x40U;
- PM0 &= 0xBFU;
- /* Set SCK00 pin */
- PMC1 &= 0xFEU;
- P1 |= 0x01U;
- PM1 &= 0xFEU;
- }
复制代码
那么怎么读写呢?其实很简单,往SIO00里面丢个数据就发了,然后过一会可以从SIO00里面捞数据了。
- uint8_t CSI_RW(uint8_t mydata)
- {
- SIO00=mydata;
- while(CSIIF00==0);
- CSIIF00=0;
- return SIO00;
- }
复制代码
官方例程中的发送多个SPI数据使用了中断,但是这个没有必要,因为在高速SPI下,发送速度是比较快的,使用中断可能更加消耗资源。所以我们来看看各种状态寄存器。最主要的就是SSR00。
SSR00必须8位读取,最主要就是bit6,TSF00,运行指示,0x40。其他bit5,SDR00L的有效数据指示,可以防止写寄存器太快,比如还没有读取完就开始往里面写。最低3位是错误指示,基本和UART有关。
然后就是启停,直接抄官方代码。
- void CSI00_Start(void)
- {
- CSIIF00 = 0U; /* clear INTCSI00 interrupt flag */
- //CSIMK00 = 0U; /* enable INTCSI00 */
- CKO0 =0;//|= 0x01U; /* CSI00 clock initial level */
- SO0 &= (uint8_t)~0x01U; /* CSI00 SO initial level */
- SOE0 |= 0x01U; /* enable CSI00 output */
- SS0 |= 0x01U; /* enable CSI00 */
- }
- void CSI00_Stop(void)
- {
- ST0 |= 0x0001U; /* disable CSI00 */
- SOE0 &= (uint8_t)~0x01U; /* disable CSI00 output */
- CSIMK00 = 1U; /* disable INTCSI00 interrupt */
- CSIIF00 = 0U; /* clear INTCSI00 interrupt flag */
- }
复制代码
最后,CSIMK00置1,屏蔽中断,只通过CSIIF00查询,因为SPI的读取也是由主机发起的,所以接收数据的时机完全由主机控制,无需中断。
|
|