[原创]
【Atmel SAM R21】使用SPI驱动微雪LCD
看着论坛大神都开始可劲折腾zigbee楼主还在折腾基本外设
这几天简单看了看R21的SPI外设
手上有几块LCD,不过都是并口的,还好微雪的LCD支持SPI
这货的LCD驱动IC是BD663474,触摸IC是XPT2046,今天先驱动一下LCD,触摸后面再折腾
不过这货够奇葩的,有图有真相
没错,您没眼花,居然是一块Altera的CPLD
官方文档解释说这块CPLD是把SPI接口转成8086并行接口,与BD663474通信
但是BD663474却这样说
BD663474驱动IC直接原生就支持SPI啊,楼主也是醉了,有钳就是要横着走
就是这么个接口,让楼主用R21的SPI外设驱动这块LCD,花了2天时间
先看看ASF中的SPI驱动吧,鬼佬的编程思维很有意思
对于SPI-maste的配置,顶层就有spi_module、spi_config俩个结构体
这俩结构体下面有包含许多的enum数据类型,原来都在枚举啊
看看spi_config:- struct spi_config {
- /** SPI mode. */
- enum spi_mode mode;
- /** Data order. */
- enum spi_data_order data_order;
- /** Transfer mode. */
- enum spi_transfer_mode transfer_mode;
- /** MUX setting. */
- enum spi_signal_mux_setting mux_setting;
- /** SPI character size. */
- enum spi_character_size character_size;
- /** Enabled in sleep modes. */
- bool run_in_standby;
- /** Enable receiver. */
- bool receiver_enable;
- # ifdef FEATURE_SPI_SLAVE_SELECT_LOW_DETECT
- /** Enable Slave Select Low Detect. */
- bool select_slave_low_detect_enable;
- # endif
- # ifdef FEATURE_SPI_HARDWARE_SLAVE_SELECT
- /** Enable Master Slave Select. */
- bool master_slave_select_enable;
- # endif
- /** Union for slave or master specific configuration. */
- union {
- /** Slave specific configuration. */
- struct spi_slave_config slave;
- /** Master specific configuration. */
- struct spi_master_config master;
- } mode_specific;
- /** GCLK generator to use as clock source. */
- enum gclk_generator generator_source;
- /** PAD0 pinmux. */
- uint32_t pinmux_pad0;
- /** PAD1 pinmux. */
- uint32_t pinmux_pad1;
- /** PAD2 pinmux. */
- uint32_t pinmux_pad2;
- /** PAD3 pinmux. */
- uint32_t pinmux_pad3;
- };
再去查看枚举类型spi_mode:
- <b><font size="3">enum spi_mode {
- /** Master mode. */
- SPI_MODE_MASTER = 1,
- /** Slave mode. */
- SPI_MODE_SLAVE = 0,
- };</font></b>
转来转去,人就晕菜了
给ATMEL写库函数的哥们,以前肯定是写Linux代码的
初学者看几次就想抽人了,这生态圈,只给大牛们玩啊
好吧,不吐槽了,来驱动LCD
SPI需要配置的东西相对比较多,譬如主从、发送顺序、发送模式、发送字节数等等
这些都在spi_get_config_defaults这个函数中有处理,这个函数在spi.h文件里头
- <b><font size="3">static inline void spi_get_config_defaults(
- struct spi_config *const config)
- {
- /* Sanity check arguments */
- Assert(config);
-
- /* Default configuration values */
- config->mode = SPI_MODE_MASTER;
- config->data_order = SPI_DATA_ORDER_MSB;
- config->transfer_mode = SPI_TRANSFER_MODE_0;
- config->mux_setting = SPI_SIGNAL_MUX_SETTING_D;
- config->character_size = SPI_CHARACTER_SIZE_8BIT;
- config->run_in_standby = false;
- config->receiver_enable = false;
- # ifdef FEATURE_SPI_SLAVE_SELECT_LOW_DETECT
- config->select_slave_low_detect_enable= true;
- # endif
- # ifdef FEATURE_SPI_HARDWARE_SLAVE_SELECT
- config->master_slave_select_enable= false;
- # endif
- config->generator_source = GCLK_GENERATOR_0;
-
- /* Clear mode specific config */
- memset(&(config->mode_specific), 0, sizeof(config->mode_specific));
-
- /* Master config defaults */
- config->mode_specific.master.baudrate = 500000;
-
- /* pinmux config defaults */
- config->pinmux_pad0 = PINMUX_DEFAULT;
- config->pinmux_pad1 = PINMUX_DEFAULT;
- config->pinmux_pad2 = PINMUX_DEFAULT;
- config->pinmux_pad3 = PINMUX_DEFAULT;
-
- };</font></b>
如果要配置这些,就得去修改
或者通过spi_config结构体去调整
对比BD663474的时序:
时钟空闲为高,第二个时钟边沿采样
看看R21的SPI模式:
- <b><font size="3">enum spi_transfer_mode {
- /** Mode 0. Leading edge: rising, sample. Trailing edge: falling, setup. */
- SPI_TRANSFER_MODE_0 = 0,
- /** Mode 1. Leading edge: rising, setup. Trailing edge: falling, sample. */
- SPI_TRANSFER_MODE_1 = SERCOM_SPI_CTRLA_CPHA,
- /** Mode 2. Leading edge: falling, sample. Trailing edge: rising, setup. */
- SPI_TRANSFER_MODE_2 = SERCOM_SPI_CTRLA_CPOL,
- /** Mode 3. Leading edge: falling, setup. Trailing edge: rising, sample. */
- SPI_TRANSFER_MODE_3 = SERCOM_SPI_CTRLA_CPHA | SERCOM_SPI_CTRLA_CPOL,
- };</font></b>
从那么在R21的spi配置中,应该是属于MODE 3呀
按照这个思路,捣鼓了一晚上,啥都末出现
回头看了看Open1081的代码,恍然大悟
- <b><font size="3">SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
- SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
- SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
- SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
- SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
- SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
- SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;</font></b>
SPI_CPHA_1Edge+SPI_CPOL_Low,这货配置的SPI是标准MODE 0啊
估计经过了那块接口转换的CPLD,SPI定制成了MODE 0
BD663474本身的SPI接口其实根本就没有使用
坑爹啊,调了2个晚上了
还好最终解决问题主函数代码:
- int main(void)
- {
- SystemInit();
- configure_usart();
- usart_write_buffer_wait(&usart_instance, "test\r\n", sizeof("test\r\n"));
- LCD_RST;
- delay_ms(10);
- LCD_RST_DONE;
- LCD_Initializtion();
- LCD_Clear(Yellow);
- GUI_Text(0,170,"Welcome SAMR21 Xplained Pro",Red,Yellow);
- GUI_Text(0,186,"Hello,EEWorld!! I'm Ljj3166!",Red,Yellow);
- LCD_DrawLine(0,120,239,120,Red);
- LCD_DrawLine(0,121,239,121,Red);
- LCD_DrawLine(0,0,0,120,Red);
- LCD_DrawLine(0,1,0,121,Red);
- LCD_DrawLine(40,40,40,120,Red);
- LCD_DrawLine(41,41,41,121,Red);
- LCD_DrawLine(80,80,80,120,Red);
- LCD_DrawLine(81,81,81,121,Red);
- LCD_DrawLine(100,100,100,120,Red);
- LCD_DrawLine(101,101,101,121,Red);
- while (true) {
- delay_ms(300);
- port_pin_toggle_output_level(LED0);
- }
- }
有图有视频,才是真的有真相
R21的时钟还整得不是很清楚,有待进一步了解
下次该折腾触摸了
本帖最后由 ljj3166 于 2015-1-10 18:08 编辑
这个不错 我也需要驱动个LCD
生活就是油盐酱醋再加一点糖,快活就是一天到晚乐呵呵的忙
===================================
做一个简单的人,踏实而务实,不沉溺幻想,不庸人自扰
历害啊,顶你一下
http://shop34182318.taobao.com/
https://shop436095304.taobao.com/?spm=a230r.7195193.1997079397.37.69fe60dfT705yr
不知如何才能在任意树莓派3的系统上加载驱动…… 期待后续……
楼主,能否加我微信,特别需要请教下,Samr21。我微信号525489751