xld0932

个性签名:We are a team and we work as a team !

  • 2024-10-17
  • 加入了学习《DIY作品演示》,观看 【HC32F460开发板测评】06.模拟I2C实现OLED显示

  • 2024-07-12
  • 加入了学习《DIY作品演示》,观看 【GD32L233C-START评测】03.WS2812B驱动实现之PWM+DMA

  • 加入了学习《DIY作品演示》,观看 【GD32L233C-START评测】04.WS2812B驱动实现之SPI

  • 2024-05-10
  • 回复了主题帖: HC32F460,嘀嗒延时问题?

    本帖最后由 xld0932 于 2024-5-10 09:34 编辑 1、官方的DDL_DelayMS函数是软件方式延时,根据当前配置的HCLK时钟频率进行计数,时间不算太精确 2、在官网可以下载当前的驱动库和样例,在HC32F460_DDL_Rev3.2.0\projects\ev_hc32f460_lqfp100_v2\examples\systick\systick_int有对应的示例程序,可参考例程实现你需要的SysTick延时函数功能 3、在你delay_init配置SysTick时,如果不需要用到中断的方式,就不要配置中断,配置了中断,就要实现中断函数

  • 2024-03-26
  • 发表了主题帖: 【国民技术车规MCU N32A455开发板】07.熟悉板载VS1053B CODEC模块,通过I2S播放录音

    1.概述 国民技术N32A455系列MCU支持3路SPI接口及2路I2S接口。SPI允许芯片与外部设备以半/全双工、同步、串行方式通信。此接口可以被配置成主模式,并为外部从设备提供通信时钟(SCK)。接口还能以多主配置方式工作。它可用于多种用途,包括使用一条双向数据线的双线单工同步传输,还可使用CRC校验的可靠通信。I2S也是一种3引脚的同步串行接口通讯协议, 2个标准的I2S接口(与SPI2和SPI3复用)可以工作于主或从模式,这2个接口可以配置为16位、 24位或32位传输,亦可配置为输入或输出通道,支持音频采样频率从8kHz到96kHz。它支持四种音频标准,包括飞利浦I2S标准, MSB和LSB对齐标准,以及PCM标准。   2.原理图 开发板选用CODEC芯片(VS1053B),输入LINE_IN接口J19以及驻极体MIC U16,一路耳机输出接口J21, 经过功放芯片(HT6872)输出一路外置喇叭接口SPK1&SPK2。 CODEC芯片位号U15,功放芯片(HT6872)位号U18。 CODEC支持SPI以及I2S两种通讯,若选用SPI通讯,则需连接跳线J46、 J47;若选用I2S通讯,则需连接跳线J37、 J38。   3.硬件环境 通过一个耳机连接到J21作为LINE_IN,通过咪头作为LINE_IN输入端口,根据说明,连接相应的跳线帽,如下所示:   4.录音、存储、播放 4.1.按键初始化及扫描 /** * [url=home.php?mod=space&uid=159083]@brief[/url] Initializes the peripherals used by the KEY driver. */ void KEY_Init(void) { GPIO_InitType GPIO_InitStructure; /*!< KEY, KEY0-KEY1 , KEY3 Periph clock enable */ RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD | RCC_APB2_PERIPH_GPIOC, ENABLE); GPIO_InitStructure.Pin = GPIO_PIN_12; //KEY0 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure); GPIO_InitStructure.Pin = GPIO_PIN_6|GPIO_PIN_7;//KEY1-KEY2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure); } /** * @brief scan key */ uint8_t KEY_Scan(uint8_t mode) { static uint8_t key_up = 1; if(mode)key_up = 1; if(key_up && (KEY0 == 0 || KEY1== 0 || KEY2== 0)) { delay_ms(10); key_up = 0; if(KEY0 == 0)return KEY0_PRES; else if(KEY1 == 0)return KEY1_PRES; else if(KEY2 == 0)return KEY2_PRES; }else if(KEY0 == 1 && KEY1 == 1 && KEY2 == 1)key_up = 1; return 0; }   4.2.SPI FLASH初始化配置 /** * @brief Initializes the peripherals used by the SPI FLASH driver. */ void sFLASH_Init(void) { SPI_InitType SPI_InitStructure; sFLASH_LowLevel_Init(); /*!< Deselect the FLASH: Chip Select high */ sFLASH_CS_HIGH(); /*!< SPI configuration */ SPI_InitStructure.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX; SPI_InitStructure.SpiMode = SPI_MODE_MASTER; SPI_InitStructure.DataLen = SPI_DATA_SIZE_8BITS; SPI_InitStructure.CLKPOL = SPI_CLKPOL_HIGH; SPI_InitStructure.CLKPHA = SPI_CLKPHA_SECOND_EDGE; SPI_InitStructure.NSS = SPI_NSS_SOFT; SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_4; SPI_InitStructure.FirstBit = SPI_FB_MSB; SPI_InitStructure.CRCPoly = 7; SPI_Init(sFLASH_SPI, &SPI_InitStructure); /*!< Enable the sFLASH_SPI */ SPI_Enable(sFLASH_SPI, ENABLE); }   4.3.VS1053复位及初始化 /** * @brief vs1053b init */ void VS_Init(void) { GPIO_InitType GPIO_InitStructure; RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_GPIOB | RCC_APB2_PERIPH_GPIOC, ENABLE); GPIO_InitStructure.Pin = VS_DREQ_PIN; //PB11 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitPeripheral(VS_DREQ_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = VS_RST_PIN; //PB0 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitPeripheral(VS_RST_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = VS_XCS_PIN;//PC2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitPeripheral(VS_XCS_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = VS_XDCS_PIN;//PA3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitPeripheral(VS_XDCS_PORT, &GPIO_InitStructure); SPI3_Init(); } /** * @brief vs1053b soft reset */ void VS_Soft_Reset(void) { uint8_t retry=0; while(VS_DQ==0); //wait soft reset finish VS_SPI_ReadWriteByte(0Xff); retry=0; while(VS_RD_Reg(SPI_MODE)!=0x0800) { VS_WR_Cmd(SPI_MODE,0x0804); //soft reset delay_ms(2);//wait at least 1.35ms if(retry++>100)break; } while(VS_DQ==0);//wait soft reset finish retry=0; while(VS_RD_Reg(SPI_CLOCKF)!=0X9800) { VS_WR_Cmd(SPI_CLOCKF,0X9800);//set vs10xx clock if(retry++>100)break; } delay_ms(20); } /** * @brief vs1053b hardware reset * [url=home.php?mod=space&uid=784970]@return[/url] 1:reset fail; 0:reset success */ uint8_t VS_HD_Reset(void) { uint16_t retry=0; VS_RST = 0; delay_ms(20); VS_XDCS = 1; VS_XCS = 1; VS_RST = 1; while(VS_DQ==0&&retry<200)//wait buf free { retry++; delay_us(50); }; delay_ms(20); if(retry>=200) { return 1; } else { return 0; } }   4.4.固定频率音频测试 /** * @brief vs1053b sine test */ void VS_Sine_Test(void) { VS_HD_Reset(); VS_WR_Cmd(SPI_VOL,0x5050); //set vol VS_WR_Cmd(SPI_MODE,0x0820);//enter test mode while(VS_DQ==0); //wait buf free printf("mode sin:%x\r\n",VS_RD_Reg(SPI_MODE)); printf("sine freq=6000Hz\r\n"); //send sine test command:0x53 0xef 0x6e n 0x00 0x00 0x00 0x00 //n = 0x24, set VS10XX sine frequency VS_SPI_SpeedLow();//set spi speed low VS_XDCS=0; VS_SPI_ReadWriteByte(0x53); VS_SPI_ReadWriteByte(0xef); VS_SPI_ReadWriteByte(0x6e); VS_SPI_ReadWriteByte(0x30); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); delay_100ms(25); VS_XDCS=1; delay_ms(100); //exit sine test VS_XDCS=0; VS_SPI_ReadWriteByte(0x45); VS_SPI_ReadWriteByte(0x78); VS_SPI_ReadWriteByte(0x69); VS_SPI_ReadWriteByte(0x74); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); delay_ms(100); VS_XDCS=1; delay_ms(100); VS_HD_Reset(); VS_WR_Cmd(SPI_VOL,0x5050); //set vol VS_WR_Cmd(SPI_MODE,0x0820);//enter test mode while(VS_DQ==0); //wait buf free printf("mode sin:%x\r\n",VS_RD_Reg(SPI_MODE)); printf("sine freq=1000Hz\r\n"); //send sine test command:0x53 0xef 0x6e n 0x00 0x00 0x00 0x00 //n = 0x24, set VS10XX sine frequency VS_SPI_SpeedLow();//set spi speed low //send sine test command:0x53 0xef 0x6e n 0x00 0x00 0x00 0x00 //n = 0x44, set VS10XX sine frequency VS_XDCS=0; VS_SPI_ReadWriteByte(0x53); VS_SPI_ReadWriteByte(0xef); VS_SPI_ReadWriteByte(0x6e); VS_SPI_ReadWriteByte(0x44); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); delay_100ms(25); VS_XDCS=1; delay_ms(100); //exit sine test VS_XDCS=0; VS_SPI_ReadWriteByte(0x45); VS_SPI_ReadWriteByte(0x78); VS_SPI_ReadWriteByte(0x69); VS_SPI_ReadWriteByte(0x74); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); delay_ms(100); VS_XDCS=1; delay_ms(100); }   4.5.按键功能实现 /** * @brief recoder play * @return play result */ uint8_t recoder_play(void) { uint8_t key; uint8_t rval=0; __WaveHeader *wavhead=0; unsigned int sectorsize=0; uint8_t *recbuf = {0}; uint16_t w; uint16_t idx=0; uint8_t rec_sta=0;//recoder state //[7]:0,no recoder;1,exit recoder; //[6:1]:reserve //[0]:0,recoding;1,pause recode uint8_t recagc=4; //default gain uint8_t playFlag=0; //recoder play flag wavhead=(__WaveHeader*)mymalloc(sizeof(__WaveHeader)); if(wavhead==NULL)rval=1; recbuf=mymalloc(DATASIZE); if(recbuf==NULL)rval=1; if(rval==0) { while(VS_RD_Reg(SPI_HDAT1)>>8); //wait buf free printf("Record test!"); while(rval==0) { key=KEY_Scan(0); switch(key) { case KEY0_PRES: //REC/PAUSE printf("key0:rec is down\r\n"); if(rec_sta&0X01) { rec_sta&=0XFE;//pausing, cancel pause } else if(rec_sta&0X80)//recording,pause { rec_sta|=0X01; //pause } else //no recording { printf("erase flash,please wait a moment\r\n"); erase_recoder_file_in_flash(); printf("start rec\r\n"); while(VS_HD_Reset()); VS_Soft_Reset(); recoder_enter_rec_mode(recagc*1024); while((VS_RD_Reg(SPI_HDAT1)>>8)); rec_sta|=0X80; //start recode recoder_wav_init(wavhead);//init WAV data delay_ms(200); } break; case KEY1_PRES: //STOP&SAVE printf("key1:stop/save is down\r\n"); if(rec_sta&0X80)//exit record data { wavhead->riff.ChunkSize=sectorsize*DATASIZE+36; //all file size wavhead->data.ChunkSize=sectorsize*DATASIZE; //data size W25QXX_Write((uint8_t*)wavhead, RECORDERADDR-44, sizeof(__WaveHeader));//write WaveHeader data 44Byte printf("save file in flash ok!all file size=%dkByte\r\n",(sectorsize*DATASIZE+44)/1024); sectorsize=0; } rec_sta=0; break; case KEY2_PRES://play record printf("wk_up:play is down\r\n"); if(rec_sta==0) { playFlag=1; } break; } //read data from vs1053b if(rec_sta==0X80) { w=VS_RD_Reg(SPI_HDAT1); //get vs1053b buf exit data count if((w>=256 && w<=896)) { idx=0; while(idx<DATASIZE) { w=VS_RD_Reg(SPI_HDAT0); //get data recbuf[idx++]=w&0XFF; recbuf[idx++]=w>>8; } if(sectorsize<1024*1024/DATASIZE)//recoder max size 1M { sFLASH_WriteBuffer(recbuf,RECORDERADDR+sectorsize*DATASIZE,DATASIZE);//write data to flash 512 byte sectorsize++; } else { sectorsize=1024*1024/DATASIZE; printf("err:flash is all,sectorsize=%d\r\n",sectorsize); } } } else { if(playFlag) { printf("play:\r\n"); rec_play_wav(); playFlag = 0; while(VS_HD_Reset()); } delay_ms(5); } } } myfree(wavhead); myfree(recbuf); return rval; }   4.6.录音相关操作 /** * @brief enter pcm recoder mode */ void recoder_enter_rec_mode(uint16_t agc) { while(VS_DQ==0); VS_WR_Cmd(SPI_BASS,0x0000); VS_WR_Cmd(SPI_AICTRL0,8000); //set sampling rate 8Khz VS_WR_Cmd(SPI_AICTRL1,agc); //set agc:0,default gain.1024 equal to 1,512 equal to 0.5, max value 65535=64 VS_WR_Cmd(SPI_AICTRL2,0); //set gain max,0, 65536=64X VS_WR_Cmd(SPI_AICTRL3,6); //MIC single left channel input PCM VS_WR_Cmd(SPI_CLOCKF,0x2000); //set vs10xx clock,MULT:2 doube frequency;ADD:not allow;CLK:12.288Mhz VS_WR_Cmd(SPI_MODE,0x1804); //MIC,recoder active delay_ms(5); //wait at least 1.35ms VS_Load_Patch((uint16_t*)wav_plugin,40);//VS1053 WAV recoder need patch } /** * @brief recoder wav init */ void recoder_wav_init(__WaveHeader* wavhead) { wavhead->riff.ChunkID=0X46464952; //"RIFF" wavhead->riff.ChunkSize=0; //size wavhead->riff.Format=0X45564157; //"WAVE" wavhead->fmt.ChunkID=0X20746D66; //"fmt " wavhead->fmt.ChunkSize=16; //16bit wavhead->fmt.AudioFormat=0X01; //0X01,PCM;0X01,IMA ADPCM wavhead->fmt.NumOfChannels=1; //single channel wavhead->fmt.SampleRate=8000; //8Khz sampling rate wavhead->fmt.ByteRate=wavhead->fmt.SampleRate*2;//16bit 2byte wavhead->fmt.BlockAlign=2; //block size,1 block = 2byte wavhead->fmt.BitsPerSample=16; //16 bit PCM wavhead->data.ChunkID=0X61746164; //"data" wavhead->data.ChunkSize=0; //data size }   4.7.存储录音 uint8_t W25QXX_BUFFER[4096]; void W25QXX_Write(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) { uint32_t secpos; uint16_t secoff; uint16_t secremain; uint16_t i; uint8_t * W25QXX_BUF; W25QXX_BUF = W25QXX_BUFFER; secpos = WriteAddr / 4096; secoff = WriteAddr % 4096; secremain = 4096 - secoff; if(NumByteToWrite <= secremain) { secremain = NumByteToWrite; } while(1) { sFLASH_ReadBuffer(W25QXX_BUF, WriteAddr, secremain); for(i = 0; i < secremain; i++) { if(W25QXX_BUF[i] != 0XFF) break;//need erase first } if(i < secremain) { sFLASH_ReadBuffer(W25QXX_BUF, secpos * 4096, 4096); //read back a sector data W25QXX_Erase_Sector(secpos); //erase the sector for(i = 0; i < secremain; i++) { W25QXX_BUF[i + secoff] = pBuffer[i]; } W25QXX_Write_NoCheck(W25QXX_BUF, secpos * 4096, 4096); } else { W25QXX_Write_NoCheck(pBuffer, WriteAddr, secremain); } if(NumByteToWrite == secremain) { break; } else { secpos++; secoff = 0; pBuffer += secremain; WriteAddr += secremain; NumByteToWrite -= secremain; if(NumByteToWrite > 4096) { secremain = 4096; } else { secremain = NumByteToWrite; } } } W25QXX_Wait_Busy(); }   4.8.播放录音 /** * @brief play wav file * @return play result */ uint8_t rec_play_wav() { uint8_t rval=0; uint8_t *databuf; uint16_t i=0; unsigned int sectorsize=0,n=0; uint16_t data_size = 512; databuf = mymalloc(data_size); if(databuf==NULL)rval=0XFF;//malloc memory fail if(rval==0) { VS_HD_Reset(); //VS hardware reset VS_Soft_Reset(); //VS software reset VS_Set_Vol(220); //set the volume VS_Reset_DecodeTime(); //reset decode time //read back file size£¬file size-8 sFLASH_ReadBuffer(databuf,RECORDERADDR-44+4,4); sectorsize+=databuf[3]<<24; sectorsize+=databuf[2]<<16; sectorsize+=databuf[1]<<8; sectorsize+=databuf[0]; if(sectorsize == 0xFFFFFFFF) { printf("no recoder file\r\n"); return 1; } sectorsize+=8;//file size VS_SPI_SpeedHigh(); while(1) { VS_XDCS = 1; sFLASH_ReadBuffer(databuf,RECORDERADDR-44+n*data_size,data_size); i=0; do { if(VS_Send_MusicData(databuf+i)==0) { i+=32;//send music data to vs } }while(i<data_size);//send 512 byte n++; if(n%2 == 0) { printf("play=%d\r\n",n/2); } if(n==((sectorsize-44)/data_size)+1) { rval=0; printf("the file size=%dkByte\r\n",sectorsize/1024); break; } VS_XDCS = 0; } } myfree(databuf); return rval; }   5.运行结果 程序启动后,先播放了3段不同频率的音频,然后通过按下S3按键开始录音,此时可以将嘴靠近MIC近一些进行说话,然后按下S4按键,将刚刚的录音保存到SPI FLASH中,最后可以通过按下S5按键来播放刚刚的录音,录音从耳机中播出   6.附件

  • 2024-03-25
  • 回复了主题帖: 【国民技术车规MCU N32A455开发板】06.熟悉SDIO接口,移植FatFs文件系统实现文件读写

    有2个地方需要注意的是,在移植FatFs后,需要对调用的SD_ReadBlock和SD_WriteBlock做一下修改,就是将这个函数的如下判断语句给注释掉: // if (CardType == SDIO_HIGH_CAPACITY_SD_CARD) // { // BlockSize = 512; // ReadAddr /= 512; // }  

  • 发表了主题帖: 【国民技术车规MCU N32A455开发板】06.熟悉SDIO接口,移植FatFs文件系统实现文件读写

    本帖最后由 xld0932 于 2024-3-25 15:38 编辑 1.概述 国民N32A455系列MCU支持1路SDIO接口,安全数字输入输出接口(Secure Digital Input and Output),简称SDIO接口, SDIO主机接口为AHB外设总线和多媒体卡(MMC)、 SD存储卡、 SDIO卡设备间提供了操作接口。SDIO时钟速率可达48MHz。   2.原理图   3.SDIO示例程序 通过官方的示例程序“Nationstech.N32A455_Library.1.1.0\projects\n32a455_EVAL\examples\SDIO\uSDCard”,测试TF卡,通过示例程序读取TF卡数据,获取TF卡信息,运行结果如下所示:   4.移植FatFs文件系统 我们先将FatFs源文件解压并添加到工程中,然后配置头文件的包含路径: 然后我们对diskio.c接口文件进行移植,直接调试官方示例程序中的应用函数,需要注意的是官方示例程序默认是DMA方式,在操作缓存的时候需要注意哦,可以参考官方示例程序的写法,具体如下所示: /*-----------------------------------------------------------------------*/ /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2019 */ /*-----------------------------------------------------------------------*/ /* If a working storage control module is available, it should be */ /* attached to the FatFs via a glue function rather than modifying it. */ /* This is an example of glue functions to attach various exsisting */ /* storage control modules to the FatFs module with a defined API. */ /*-----------------------------------------------------------------------*/ #include "ff.h" /* Obtains integer types */ #include "diskio.h" /* Declarations of disk functions */ #include <stdio.h> #include "sdio_sdcard.h" #define diskio_BLOCK_SIZE 512 #pragma pack(4) u32 diskio_Buffer_Block_Tx[diskio_BLOCK_SIZE / 4]; u32 diskio_Buffer_Block_Rx[diskio_BLOCK_SIZE / 4]; #pragma pack() #define diskio_Buffer_Block_Tx ((uint8_t *)diskio_Buffer_Block_Tx) #define diskio_Buffer_Block_Rx ((uint8_t *)diskio_Buffer_Block_Rx) /*-----------------------------------------------------------------------*/ /* Get Drive Status */ /*-----------------------------------------------------------------------*/ DSTATUS disk_status ( BYTE pdrv /* Physical drive nmuber to identify the drive */ ) { return RES_OK; } /*-----------------------------------------------------------------------*/ /* Inidialize a Drive */ /*-----------------------------------------------------------------------*/ DSTATUS disk_initialize ( BYTE pdrv /* Physical drive nmuber to identify the drive */ ) { return RES_OK; } /*-----------------------------------------------------------------------*/ /* Read Sector(s) */ /*-----------------------------------------------------------------------*/ DRESULT disk_read ( BYTE pdrv, /* Physical drive nmuber to identify the drive */ BYTE *buff, /* Data buffer to store read data */ LBA_t sector, /* Start sector in LBA */ UINT count /* Number of sectors to read */ ) { for (UINT i = 0; i < count; i++) { SD_ReadBlock(diskio_Buffer_Block_Rx, sector++, SDCardInfo.CardBlockSize); SD_WaitReadOperation(); for (UINT j = 0; j < SDCardInfo.CardBlockSize; j++) { buff[i * 512 + j] = diskio_Buffer_Block_Rx[j]; } } return RES_OK; } /*-----------------------------------------------------------------------*/ /* Write Sector(s) */ /*-----------------------------------------------------------------------*/ #if FF_FS_READONLY == 0 DRESULT disk_write ( BYTE pdrv, /* Physical drive nmuber to identify the drive */ const BYTE *buff, /* Data to be written */ LBA_t sector, /* Start sector in LBA */ UINT count /* Number of sectors to write */ ) { for (UINT i = 0; i < count; i++) { for (UINT j = 0; j < SDCardInfo.CardBlockSize; j++) { diskio_Buffer_Block_Tx[j] = buff[i * 512 + j]; } SD_WriteBlock(diskio_Buffer_Block_Tx, sector++, SDCardInfo.CardBlockSize); SD_WaitWriteOperation(); } return RES_OK; } #endif /*-----------------------------------------------------------------------*/ /* Miscellaneous Functions */ /*-----------------------------------------------------------------------*/ DRESULT disk_ioctl ( BYTE pdrv, /* Physical drive nmuber (0..) */ BYTE cmd, /* Control code */ void *buff /* Buffer to send/receive control data */ ) { DRESULT res = RES_OK; switch(cmd) { case CTRL_SYNC: break; case GET_SECTOR_COUNT: *(WORD *)buff = SDCardInfo.CardCapacity / SDCardInfo.CardBlockSize; break; case GET_SECTOR_SIZE: *(WORD *)buff = SDCardInfo.CardBlockSize; break; case GET_BLOCK_SIZE: *(WORD *)buff = 1; break; default: res = RES_PARERR; break; } return res; } DWORD get_fattime(void) { DWORD ret_val = 0; /* 2020-10-12 18:05:10 */ ret_val = (20 << 25) + (10 << 21) + (12 << 16) + (18 << 11) + (05 << 5) + (10 / 2); return ret_val; }   5.文件读写操作 在移植好FatFs文件系统后,我们就来编写一个文件系统的挂载、对文件的打开、关闭、读写这些基本操作的演示函数,如下所示: #include <string.h> #include "ff.h" #include "diskio.h" #include "ffconf.h" void File_System_Initialize(void) { FATFS FatFs; FIL File; UINT br = 0, bw = 0; FRESULT Result; uint8_t Buffer[200]; memset(Buffer, 0, sizeof(Buffer)); Result = f_mount(&FatFs, "0:", 1); if(Result) { printf("\r\nf_mount Fail! Result = %d\r\n", Result); } else { Result = f_open(&File, "0:/HELLO.TXT", FA_READ); if(Result != RES_OK) { printf("\r\nf_open HELLO.txt Fail! Result = %d\r\n", Result); } else { do { Result = f_read(&File, Buffer, 200, &br); if(br != 0) printf("\r\nf_read : %s\r\n", Buffer); } while(br != 0); f_close(&File); } Result = f_open(&File, "0:/TEST.TXT", FA_CREATE_ALWAYS | FA_WRITE); if (Result != RES_OK) { printf("\r\nf_open TEST.txt Fail! Result = %d\r\n", Result); } else { Result = f_write(&File, "TEST...", 7, &bw); if (Result != RES_OK) { printf("\r\nf_write TEST.txt Fail! Result = %d\r\n", Result); } else { printf("\r\nf_write TEST.txt Result = %d, bw = %d\r\n", Result, bw); f_sync(&File); } f_close(&File); } } }   6.运行结果 能够正确的读取到TF卡中文件的数据内容,以及创建新文件并写入相应内容,并返回正常的写入状态值,如下图所示:   7.附件

  • 2024-03-16
  • 回复了主题帖: 【国民技术车规MCU N32A455开发板】05、通过硬件I2C熟悉板载EEPROM的操作和应用

    lugl4313820 发表于 2024-3-16 06:59 DMA的方式比普通的读取在快好多倍呀? 读写的速度是一样的呀,只是DMA可以释放MCU资源去做其它事情……

  • 2024-03-15
  • 回复了主题帖: 【国民技术车规MCU N32A455开发板】05、通过硬件I2C熟悉板载EEPROM的操作和应用

    Jacktang 发表于 2024-3-15 07:25 国民技术N32A455系列MCU还是很强悍的

  • 2024-03-14
  • 发表了主题帖: 【国民技术车规MCU N32A455开发板】05、通过硬件I2C熟悉板载EEPROM的操作和应用

    1.概述 国民技术N32A455系列MCU搭载了多达4个独立的I2C总线接口,它提供多主机功能,控制所有I2C总线特定的时序、协议、仲裁和定时。支持多种通信速率模式(最高支持1MHz),支持DMA操作,同时与SMBus 2.0兼容。 I2C模块有多种用途,包括CRC码的生成和校验、 SMBus(系统管理总线—System Management Bus)和PMBus(电源管理总线—PowerManagement Bus)。   2.N32A455开发板EEPROM原理图 开发板选用EEROM芯片(CAT24C08YI-GT3),分别连接到硬件I2C1的PB8和PB9这两个引脚上,EEPROM的A0~A2地址选择引脚都连接了GND,如下所示:   3.I2C示例程序 通过I2C模块与外部EEPRON的通信,对EEPROM进行读取操作,熟悉I2C的编程和应用方法: int main(void) { uint16_t i = 0; log_init(); log_info("this is a I2C EEPROM demo\r\n"); /* Initialize the I2C EEPROM driver ----------------------------------------*/ I2C_EE_Init(); /* Fill the buffer to send */ for (i = 0; i < TEST_EEPROM_SIZE; i++) { tx_buf[i] = i; } log_info("\r\nWrite to I2C EEPROM..."); /* First write in the memory followed by a read of the written data --------*/ /* Write to I2C EEPROM from TEST_EEPROM_ADDR */ I2C_EE_WriteBuffer(tx_buf, TEST_EEPROM_ADDR, TEST_EEPROM_SIZE); log_info("\r\nRead from I2C EEPROM :"); /* Read from I2C EEPROM from sEE_READ_ADDRESS1 */ I2C_EE_ReadBuffer(rx_buf, TEST_EEPROM_ADDR, TEST_EEPROM_SIZE); for (i = 0; i < TEST_EEPROM_SIZE; i++) { if ((i % 16) == 0) { printf("\r\n"); } printf("0x%02X ", rx_buf[i]); } printf("\r\n"); /* Check if the data written to the memory is read correctly */ test_status = Buffercmp(tx_buf, rx_buf, TEST_EEPROM_SIZE); if (test_status == PASSED) { log_info("\r\nthe write and read data are the same,I2C EEPROM test pass\r\n"); } else { log_info("\r\nthe write and read data are different,I2C EEPROM test fail\r\n"); } while (1) { } }   EEPROM写PAGE操作: 写PAGE操作实现了查访和DMA两种方式,操作流程都相同,都是先产生START信号、发送器件地址、发送写入地址、写入数据、最后发送STOP停止位;每一个步骤都对应一个事件检测,判断是否操作完成: void I2C_EE_PageWrite(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite) { #if PROCESS_MODE == 0 /* polling */ sEETimeout = sEE_LONG_TIMEOUT; while (I2C_GetFlag(I2Cx, I2C_FLAG_BUSY)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Send START condition */ I2C_GenerateStart(I2Cx, ENABLE); /** Test on EV5 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_MODE_FLAG)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Send EEPROM address for write */ I2C_SendAddr7bit(I2Cx, EEPROM_ADDRESS, I2C_DIRECTION_SEND); /** Test on EV6 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_TXMODE_FLAG)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Send the EEPROM's internal address to write to */ I2C_SendData(I2Cx, WriteAddr); /** Test on EV8 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_DATA_SENDED)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** While there is data to be written */ while (NumByteToWrite--) { /** Send the current byte */ I2C_SendData(I2Cx, *pBuffer); /** Point to the next byte to be written */ pBuffer++; /** Test on EV8 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_DATA_SENDED)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } } /** Send STOP condition */ I2C_GenerateStop(I2Cx, ENABLE); I2C_EE_WaitEepromStandbyState(); I2C_EE_WriteOnePageCompleted(); #elif PROCESS_MODE == 1 /* interrupt */ /** initialize static parameter */ MasterDirection = Transmitter; i2c_comm_state = COMM_PRE; /** initialize static parameter according to input parameter */ SlaveADDR = EEPROM_ADDRESS; /// this byte shoule be send by F/W (in loop or INTSTS way) DeviceOffset = WriteAddr; /// this byte can be send by both F/W and DMA OffsetDone = FALSE; memcpy(SendBuf, pBuffer, NumByteToWrite); BufCount = 0; Int_NumByteToWrite = NumByteToWrite; I2C_ConfigAck(I2C1, ENABLE); I2C_ConfigInt(I2C1, I2C_INT_EVENT | I2C_INT_BUF | I2C_INT_ERR, ENABLE); /** Send START condition */ sEETimeout = sEE_LONG_TIMEOUT; while (I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } I2C_GenerateStart(I2C1, ENABLE); I2C_EE_WaitOperationIsCompleted(); I2C_EE_WriteOnePageCompleted(); #elif PROCESS_MODE == 2 /* DMA */ DMA_InitType DMA_InitStructure; /** DMA initialization */ DMA_DeInit(DMA1_CH6); DMA_InitStructure.PeriphAddr = (u32)&I2Cx->DAT; /// (u32)I2C1_DR_Address; DMA_InitStructure.MemAddr = (u32)pBuffer; /// from function input parameter DMA_InitStructure.Direction = DMA_DIR_PERIPH_DST; /// fixed for send function DMA_InitStructure.BufSize = NumByteToWrite; /// from function input parameter DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE; // fixed DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE; /// fixed DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE; /// fixed DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_Byte; /// fixed DMA_InitStructure.CircularMode = DMA_MODE_NORMAL; /// fixed DMA_InitStructure.Priority = DMA_PRIORITY_VERY_HIGH; /// up to user DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE; /// fixed DMA_Init(DMA1_CH6, &DMA_InitStructure); sEETimeout = sEE_LONG_TIMEOUT; while (I2C_GetFlag(I2Cx, I2C_FLAG_BUSY)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Send START condition */ I2C_GenerateStart(I2Cx, ENABLE); /** Test on EV5 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_MODE_FLAG)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Send EEPROM address for write */ I2C_SendAddr7bit(I2Cx, EEPROM_ADDRESS, I2C_DIRECTION_SEND); /** Test on EV6 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_TXMODE_FLAG)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Send the EEPROM's internal address to write to */ I2C_SendData(I2Cx, WriteAddr); /** Test on EV8 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_DATA_SENDING)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } DMA_EnableChannel(DMA1_CH6, ENABLE); I2C_EnableDMA(I2C1, ENABLE); sEETimeout = sEE_LONG_TIMEOUT; while(I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Send STOP condition */ I2C_GenerateStop(I2Cx, ENABLE); I2C_EnableDMA(I2Cx, DISABLE); DMA_EnableChannel(DMA1_CH6, DISABLE); I2C_EE_WaitEepromStandbyState(); I2C_EE_WriteOnePageCompleted(); #endif }   EEPROM读取数据: EEPROM数据读取的函数,依然使用了查询和DMA两种实现方式,EEPROM的读取大小没有写入PAGE字节数的限制了;具体的操作流程:产生START信号、发送器件地址、发送读取地址、产生RESTART信号、发送读取命令、读取数据: void I2C_EE_ReadBuffer(u8* pBuffer, u16 ReadAddr, u16 NumByteToRead) { #if PROCESS_MODE == 0 /* polling */ sEETimeout = sEE_LONG_TIMEOUT; while (I2C_GetFlag(I2Cx, I2C_FLAG_BUSY)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } I2C_ConfigNackLocation(I2Cx, I2C_NACK_POS_CURRENT); // clear ACKPOS I2C_ConfigAck(I2Cx, ENABLE); /** Send START condition */ I2C_GenerateStart(I2Cx, ENABLE); /** Test on EV5 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_MODE_FLAG)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Send EEPROM address for write */ I2C_SendAddr7bit(I2Cx, EEPROM_ADDRESS, I2C_DIRECTION_SEND); /** Test on EV6 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_TXMODE_FLAG)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Clear EV6 by setting again the PE bit */ I2C_Enable(I2Cx, ENABLE); /** Send the EEPROM's internal address to write to */ I2C_SendData(I2Cx, ReadAddr); /** Test on EV8 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_DATA_SENDED)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Send STRAT condition a second time */ I2C_GenerateStart(I2Cx, ENABLE); /** Test on EV5 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_MODE_FLAG)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Send EEPROM address for read */ I2C_SendAddr7bit(I2Cx, EEPROM_ADDRESS, I2C_DIRECTION_RECV); sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_GetFlag(I2Cx, I2C_FLAG_ADDRF)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** While there is data to be read */ if (NumByteToRead == 1) { /** Disable Acknowledgement */ I2C_ConfigAck(I2Cx, DISABLE); (void)(I2Cx->STS1); /// clear ADDR (void)(I2Cx->STS2); I2C_GenerateStop(I2Cx, ENABLE); } else if (NumByteToRead == 2) { I2C_ConfigNackLocation(I2Cx, I2C_NACK_POS_NEXT); // set ACKPOS (void)(I2Cx->STS1); (void)(I2Cx->STS2); I2C_ConfigAck(I2Cx, DISABLE); } else { I2C_ConfigAck(I2Cx, ENABLE); (void)(I2Cx->STS1); (void)(I2Cx->STS2); } while (NumByteToRead) { if (NumByteToRead <= 3) { /** One byte */ if (NumByteToRead == 1) { /** Wait until RXNE flag is set */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_GetFlag(I2Cx, I2C_FLAG_RXDATNE)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Read data from DAT */ /** Read a byte from the EEPROM */ *pBuffer = I2C_RecvData(I2Cx); /** Point to the next location where the byte read will be saved */ pBuffer++; /** Decrement the read bytes counter */ NumByteToRead--; } /** Two bytes */ else if (NumByteToRead == 2) { /** Wait until BTF flag is set */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Send STOP Condition */ I2C_GenerateStop(I2Cx, ENABLE); /** Read data from DAT */ *pBuffer = I2C_RecvData(I2Cx); /** Point to the next location where the byte read will be saved */ pBuffer++; /** Decrement the read bytes counter */ NumByteToRead--; /** Read data from DAT */ *pBuffer = I2C_RecvData(I2Cx); /** Point to the next location where the byte read will be saved */ pBuffer++; /** Decrement the read bytes counter */ NumByteToRead--; } /** 3 Last bytes */ else { sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Disable Acknowledgement */ I2C_ConfigAck(I2Cx, DISABLE); /** Read data from DAT */ *pBuffer = I2C_RecvData(I2Cx); /** Point to the next location where the byte read will be saved */ pBuffer++; /** Decrement the read bytes counter */ NumByteToRead--; /** Wait until BTF flag is set */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Send STOP Condition */ I2C_GenerateStop(I2Cx, ENABLE); /** Read data from DAT */ *pBuffer = I2C_RecvData(I2Cx); /** Point to the next location where the byte read will be saved */ pBuffer++; /** Decrement the read bytes counter */ NumByteToRead--; /** Read data from DAT */ *pBuffer = I2C_RecvData(I2Cx); /** Point to the next location where the byte read will be saved */ pBuffer++; /** Decrement the read bytes counter */ NumByteToRead--; } } else { /** Test on EV7 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_DATA_RECVD_FLAG)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Read a byte from the EEPROM */ *pBuffer = I2C_RecvData(I2Cx); /** Point to the next location where the byte read will be saved */ pBuffer++; /** Decrement the read bytes counter */ NumByteToRead--; if (I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF)) { /** Read a byte from the EEPROM */ *pBuffer = I2C_RecvData(I2Cx); /** Point to the next location where the byte read will be saved */ pBuffer++; /** Decrement the read bytes counter */ NumByteToRead--; } } } #elif PROCESS_MODE == 1 /* interrupt */ I2C_pBuffer = pBuffer; MasterDirection = Receiver; /** initialize static parameter according to input parameter*/ SlaveADDR = EEPROM_ADDRESS; DeviceOffset = ReadAddr; OffsetDone = FALSE; i2c_comm_state = COMM_PRE; I2C_ConfigNackLocation(I2Cx, I2C_NACK_POS_CURRENT); // clear ACKPOS I2C_ConfigAck(I2C1, ENABLE); I2C_ConfigInt(I2C1, I2C_INT_EVENT | I2C_INT_BUF | I2C_INT_ERR, ENABLE); Int_NumByteToRead = NumByteToRead; sEETimeout = sEE_LONG_TIMEOUT; while (I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } I2C_GenerateStart(I2C1, ENABLE); I2C_EE_WaitOperationIsCompleted(); #elif PROCESS_MODE == 2 /* DMA */ /** DMA initialization */ if(NumByteToRead > 1) { DMA_InitType DMA_InitStructure; /** DMA initialization */ DMA_DeInit(DMA1_CH7); DMA_InitStructure.PeriphAddr = (u32)&I2Cx->DAT; /// (u32)I2C1_DR_Address; DMA_InitStructure.MemAddr = (u32)pBuffer; /// from function input parameter DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC; /// fixed for read function DMA_InitStructure.BufSize = NumByteToRead; /// from function input parameter DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE; /// fixed DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE; /// fixed DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE; /// fixed DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_Byte; /// fixed DMA_InitStructure.CircularMode = DMA_MODE_NORMAL; /// fixed DMA_InitStructure.Priority = DMA_PRIORITY_VERY_HIGH; /// up to user DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE; /// fixed DMA_Init(DMA1_CH7, &DMA_InitStructure); } while (I2C_GetFlag(I2Cx, I2C_FLAG_BUSY)) { if ((sEETimeout--) == 0) { sEE_TIMEOUT_UserCallback(); } } /** Send START condition */ I2C_GenerateStart(I2Cx, ENABLE); /** Test on EV5 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_MODE_FLAG)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Send EEPROM address for write */ I2C_SendAddr7bit(I2Cx, EEPROM_ADDRESS, I2C_DIRECTION_SEND); /** Test on EV6 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_TXMODE_FLAG)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Clear EV6 by setting again the PE bit */ I2C_Enable(I2Cx, ENABLE); /** Send the EEPROM's internal address to write to */ I2C_SendData(I2Cx, ReadAddr); /** Test on EV8 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_DATA_SENDED)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Send STRAT condition a second time */ I2C_GenerateStart(I2Cx, ENABLE); /** Test on EV5 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_MODE_FLAG)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Send EEPROM address for read */ I2C_SendAddr7bit(I2Cx, EEPROM_ADDRESS, I2C_DIRECTION_RECV); /* Test on EV6 and clear it */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_GetFlag(I2Cx, I2C_FLAG_ADDRF)) //EV6 { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** While there is data to be read */ if (NumByteToRead == 1) { /** Disable Acknowledgement */ I2C_ConfigAck(I2Cx, DISABLE); (void)(I2Cx->STS1); /// clear ADDR (void)(I2Cx->STS2); I2C_GenerateStop(I2Cx, ENABLE); /** Wait until RXNE flag is set */ sEETimeout = sEE_LONG_TIMEOUT; while (!I2C_GetFlag(I2Cx, I2C_FLAG_RXDATNE)) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } /** Read data from DAT */ /** Read a byte from the EEPROM */ *pBuffer = I2C_RecvData(I2Cx); } else { I2C_ConfigAck(I2Cx, ENABLE); (void)(I2Cx->STS1); (void)(I2Cx->STS2); I2C_EnableDmaLastSend(I2Cx, ENABLE); DMA_EnableChannel(DMA1_CH7, ENABLE); I2C_EnableDMA(I2Cx, ENABLE); sEETimeout = sEE_LONG_TIMEOUT; while(!(DMA_GetFlagStatus(DMA1_FLAG_TC7,DMA1))) { if ((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); } I2C_EnableDMA(I2Cx, DISABLE); DMA_EnableChannel(DMA1_CH7, DISABLE); I2C_EnableDmaLastSend(I2Cx, DISABLE); I2C_GenerateStop(I2Cx, ENABLE); } I2C_EE_WaitOperationIsCompleted(); #endif }   4.运行结果   5.工程源码

  • 发表了主题帖: 【国民技术车规MCU N32A455开发板】04、通过SPI FLASH熟悉SPI通讯(SPI1 & SPI2)

    本帖最后由 xld0932 于 2024-3-14 15:26 编辑 1.概述 国民技术N32A455系列MCU搭载了3路SPI接口,同时还具备I2S功能;SPI允许芯片与外部设备以半/全双工、同步、串行方式通信。此接口可以被配置成主模式,并为外部从设备提供通信时钟(SCK)。接口还能以多主配置方式工作。它可用于多种用途,包括使用一条双向数据线的双线单工同步传输,还可使用CRC校验的可靠通信。   2.N32A455开发板SPI FLASH原理图 开发板板载一路SPI FLASH(W25Q128JVSIQTR),占用了SPI1外设资源,通过设置跳线J29、 J30、 J31、 J32与MCU的PA4、PA5、PA6、PA7相连接,所以在做SPI FLASH实验时,需要注意跳线的连接状态   3.SPI示例程序 我们参考官方的SPI FLASH示例工程,通过SPI1接口对SPI FLASH进行读、写、擦除等操作,通过修改代码将每个过程的数据打印出来,更加的直观: int main(void) { /*!< At this stage the microcontroller clock setting is already configured, this is done through SystemInit() function which is called from startup file (startup_n32a455.s) before to branch to application main. To reconfigure the default setting of SystemInit() function, refer to system_n32a455.c file */ log_init(); LedInit(GPIOE, LED1 | LED2); LedOff(GPIOE, LED1 | LED2); /* Initialize the SPI FLASH driver */ sFLASH_Init(); /* Get SPI Flash ID */ FlashID = sFLASH_ReadID(); printf("\r\nRead ID=0x%06x",FlashID); /* Check the SPI Flash ID */ if ((FlashID == sFLASH_ID)||(FlashID == sFLASH_W25Q128_ID_DTR)) { /* OK: Turn on LED1 */ LedOn(GPIOE, LED1); /* Perform a write in the Flash followed by a read of the written data */ /* Erase SPI FLASH Sector to write on */ sFLASH_EraseSector(FLASH_SectorToErase); /* Read data from SPI FLASH memory */ sFLASH_ReadBuffer(Rx_Buffer, FLASH_ReadAddress, BufferSize); printf("\r\nRead after Erase..."); for (uint32_t i = 0; i < BufferSize; i++) { if ((i % 16) == 0) { printf("\r\n"); } printf("0x%02X ", Rx_Buffer[i]); } printf("\r\n"); /* Write Tx_Buffer data to SPI FLASH memory */ sFLASH_WriteBuffer(Tx_Buffer, FLASH_WriteAddress, BufferSize); /* Read data from SPI FLASH memory */ sFLASH_ReadBuffer(Rx_Buffer, FLASH_ReadAddress, BufferSize); printf("\r\nRead after Write..."); for (uint32_t i = 0; i < BufferSize; i++) { if ((i % 16) == 0) { printf("\r\n"); } printf("0x%02X ", Rx_Buffer[i]); } printf("\r\n"); printf("\r\n%s", Rx_Buffer); printf("\r\n"); /* Check the correctness of written dada */ TransferStatus1 = Buffercmp(Tx_Buffer, Rx_Buffer, BufferSize); if(PASSED == TransferStatus1) printf("\r\nFlash write OK."); else printf("\r\nFlash write fail."); /* TransferStatus1 = PASSED, if the transmitted and received data by SPI1 are the same */ /* TransferStatus1 = FAILED, if the transmitted and received data by SPI1 are different */ /* Perform an erase in the Flash followed by a read of the written data */ /* Erase SPI FLASH Sector to write on */ sFLASH_EraseSector(FLASH_SectorToErase); /* Read data from SPI FLASH memory */ sFLASH_ReadBuffer(Rx_Buffer, FLASH_ReadAddress, BufferSize); printf("\r\nRead after Erase..."); for (uint32_t i = 0; i < BufferSize; i++) { if ((i % 16) == 0) { printf("\r\n"); } printf("0x%02X ", Rx_Buffer[i]); } printf("\r\n"); /* Check the correctness of erasing operation dada */ for (Index = 0; Index < BufferSize; Index++) { if (Rx_Buffer[Index] != 0xFF) { TransferStatus2 = FAILED; break; } } if(PASSED == TransferStatus2) printf("\r\nSector erase OK."); else printf("\r\nSector erase fail."); /* TransferStatus2 = PASSED, if the specified sector part is erased */ /* TransferStatus2 = FAILED, if the specified sector part is not well erased */ } else { /* Error: Turn on LED2 */ LedOn(GPIOE, LED2); printf("\r\nRead ID fail."); } while (1) { } }   4.运行结果 4.1.硬件环境   4.2.运行结果   5.使用SPI2操作SPI FLASH的注意事项 N32A455开发板上的PE10\PE11\PE12\PE13这几个接口作为SPI2通讯接口,正好也没有被其它板载资源所占用,所以就使用这4个引脚来验证一下SPI2操作SPI FLASH的功能,首先需要对程序进行配置 5.1.在spi_flash.h文件中对操作SPI FLASH的接口和外设进行定义: #if 0 #define sFLASH_SPI SPI1 #define sFLASH_SPI_CLK RCC_APB2_PERIPH_SPI1 #define sFLASH_SPI_SCK_PIN GPIO_PIN_5 /* PA.05 */ #define sFLASH_SPI_SCK_GPIO_PORT GPIOA /* GPIOA */ #define sFLASH_SPI_SCK_GPIO_CLK RCC_APB2_PERIPH_GPIOA #define sFLASH_SPI_MISO_PIN GPIO_PIN_6 /* PA.06 */ #define sFLASH_SPI_MISO_GPIO_PORT GPIOA /* GPIOA */ #define sFLASH_SPI_MISO_GPIO_CLK RCC_APB2_PERIPH_GPIOA #define sFLASH_SPI_MOSI_PIN GPIO_PIN_7 /* PA.07 */ #define sFLASH_SPI_MOSI_GPIO_PORT GPIOA /* GPIOA */ #define sFLASH_SPI_MOSI_GPIO_CLK RCC_APB2_PERIPH_GPIOA #define sFLASH_CS_PIN GPIO_PIN_4 /* PA.04 */ #define sFLASH_CS_GPIO_PORT GPIOA /* GPIOA */ #define sFLASH_CS_GPIO_CLK RCC_APB2_PERIPH_GPIOA #else #define sFLASH_SPI SPI2 #define sFLASH_SPI_CLK RCC_APB1_PERIPH_SPI2 #define sFLASH_SPI_SCK_PIN GPIO_PIN_11/* PE.11 */ #define sFLASH_SPI_SCK_GPIO_PORT GPIOE /* GPIOE */ #define sFLASH_SPI_SCK_GPIO_CLK RCC_APB2_PERIPH_GPIOE #define sFLASH_SPI_MISO_PIN GPIO_PIN_12/* PA.12 */ #define sFLASH_SPI_MISO_GPIO_PORT GPIOE /* GPIOE */ #define sFLASH_SPI_MISO_GPIO_CLK RCC_APB2_PERIPH_GPIOE #define sFLASH_SPI_MOSI_PIN GPIO_PIN_13/* PA.13 */ #define sFLASH_SPI_MOSI_GPIO_PORT GPIOE /* GPIOE */ #define sFLASH_SPI_MOSI_GPIO_CLK RCC_APB2_PERIPH_GPIOE #define sFLASH_CS_PIN GPIO_PIN_10/* PE.10 */ #define sFLASH_CS_GPIO_PORT GPIOE /* GPIOE */ #define sFLASH_CS_GPIO_CLK RCC_APB2_PERIPH_GPIOE #endif   5.2.因为SPI1与SPI2这两个外设接口不在同一个总线上,所以需要对官方例程中出现外设时钟配置的地方进行修改,修改spi_flash.c文件中的函数,如下所示: void sFLASH_LowLevel_DeInit(void) { GPIO_InitType GPIO_InitStructure; /*!< Disable the sFLASH_SPI */ SPI_Enable(sFLASH_SPI, DISABLE); /*!< DeInitializes the sFLASH_SPI */ SPI_I2S_DeInit(sFLASH_SPI); /*!< sFLASH_SPI Periph clock disable */ if (sFLASH_SPI_CLK == RCC_APB2_PERIPH_SPI1) { RCC_EnableAPB2PeriphClk(sFLASH_SPI_CLK, DISABLE); } else { RCC_EnableAPB1PeriphClk(sFLASH_SPI_CLK, DISABLE); } /*!< Configure sFLASH_SPI pins: SCK */ GPIO_InitStructure.Pin = sFLASH_SPI_SCK_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitPeripheral(sFLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure); /*!< Configure sFLASH_SPI pins: MISO */ GPIO_InitStructure.Pin = sFLASH_SPI_MISO_PIN; GPIO_InitPeripheral(sFLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure); /*!< Configure sFLASH_SPI pins: MOSI */ GPIO_InitStructure.Pin = sFLASH_SPI_MOSI_PIN; GPIO_InitPeripheral(sFLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure); /*!< Configure sFLASH_CS_PIN pin: sFLASH Card CS pin */ GPIO_InitStructure.Pin = sFLASH_CS_PIN; GPIO_InitPeripheral(sFLASH_CS_GPIO_PORT, &GPIO_InitStructure); } void sFLASH_LowLevel_Init(void) { GPIO_InitType GPIO_InitStructure; /*!< sFLASH_SPI_CS_GPIO, sFLASH_SPI_MOSI_GPIO, sFLASH_SPI_MISO_GPIO and sFLASH_SPI_SCK_GPIO Periph clock enable */ RCC_EnableAPB2PeriphClk( sFLASH_CS_GPIO_CLK | sFLASH_SPI_MOSI_GPIO_CLK | sFLASH_SPI_MISO_GPIO_CLK | sFLASH_SPI_SCK_GPIO_CLK, ENABLE); /*!< sFLASH_SPI Periph clock enable */ if (sFLASH_SPI_CLK == RCC_APB2_PERIPH_SPI1) { RCC_EnableAPB2PeriphClk(sFLASH_SPI_CLK, ENABLE); } else { RCC_EnableAPB1PeriphClk(sFLASH_SPI_CLK, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP2_SPI2, ENABLE); } /*!< Configure sFLASH_SPI pins: SCK */ GPIO_InitStructure.Pin = sFLASH_SPI_SCK_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitPeripheral(sFLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure); /*!< Configure sFLASH_SPI pins: MOSI */ GPIO_InitStructure.Pin = sFLASH_SPI_MOSI_PIN; GPIO_InitPeripheral(sFLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure); /*!< Configure sFLASH_SPI pins: MISO */ GPIO_InitStructure.Pin = sFLASH_SPI_MISO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitPeripheral(sFLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure); /*!< Configure sFLASH_CS_PIN pin: sFLASH Card CS pin */ GPIO_InitStructure.Pin = sFLASH_CS_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitPeripheral(sFLASH_CS_GPIO_PORT, &GPIO_InitStructure); }   5.3.注意事项:查看SPI2使用的引脚,需要看一下复用功能,需不需要重映射配置;上例中使用了PE10~PE13,是需要进行重映射配置,要不然就无法通讯了!   5.4.SPI2测试环境   5.5.SPI2测试结果   6.工程源代码

  • 2024-02-27
  • 发表了主题帖: 【国民技术车规MCU N32A455开发板】03、熟悉LIN主从机通讯(收发数据)

    1.概述 上节我们熟悉了国民技术N32A455的CAN通讯,本节我们来熟悉国民技术N32A455的LIN通讯,在汽车电子组网应用中,通常CAN会作为高速通讯的网络,而LIN则会作为低事通讯的网络,这两个网络相互配合,实现了车机整体的通讯网络。   N32A455的LIN其实是基于通用同步异步收发器(USART)的LIN模式实现的,通过RX\TX引脚与LIN收发芯片连接,通过LIN底层通讯协议,实现LIN的数据交互。   2.LIN协议 这部分在UM手册上并没有过多的去描述,只提及到了LIN的断开帧;但在我们使用LIN通讯时,必须要先搞懂LIN通讯协议哈,所以网罗了一些LIN的资料,供大家借鉴哦   3.LIN示例程序 依据官方提供的LIN主、从机示例程序,例程功能如下:若接收到主机请求帧(0x3C)会打印接收到的8字节数据(0x0F);若接收到从机应答帧(0x3D)将发送8个字节应答数据(0x01)给到主机节点。 3.1.LIN主机实现 #include "main.h" #include "lin_master.h" M_LIN_EX_MSG M_TxMsg; void SetFrameMsg(M_LIN_EX_MSG *dst_Msg, M_LIN_EX_MSG src_Msg) { int i = 0; Memset(dst_Msg, 0, sizeof(M_LIN_EX_MSG)); dst_Msg->Check = src_Msg.Check; dst_Msg->DataLen = src_Msg.DataLen; dst_Msg->Sync = src_Msg.Sync; dst_Msg->PID = src_Msg.PID; for(i = 0; i < src_Msg.DataLen; i++) { dst_Msg->Data[i] = src_Msg.Data[i]; } log_info("SetFrameMsg ID:0x%02x\r\n", dst_Msg->PID); } void SetFramePID(M_LIN_EX_MSG *src_Msg) { uint8_t p0 = 0, p1 = 0; uint8_t LIN_ID = src_Msg->PID, PID = 0x00; p0 = (LIN_ID & 0x01) ^ ((LIN_ID & 0x02) >> 1) ^ ((LIN_ID & 0x04) >> 2) ^ ((LIN_ID & 0x10) >> 4);//???? p0 = p0 & 0x01; p1 = ~(((LIN_ID & 0x02) >> 1) ^ ((LIN_ID & 0x08) >> 3) ^ ((LIN_ID & 0x10) >> 4) ^ ((LIN_ID & 0x20) >> 5)); p1 = p1 & 0x01; PID = (p1 << 7) | (p0 << 6) | LIN_ID; src_Msg->PID = PID; log_info("p0 = %02x;p1 = %02x;PID = %02x\r\n", p0, p1, PID); } uint8_t MasterGetCheckSum(uint8_t *pData, uint8_t len) { uint16_t check_sum_temp = 0; uint8_t i; for(i = 0; i < len; i++) { check_sum_temp += pData[i]; if(check_sum_temp > 0xFF) { check_sum_temp -= 0xFF; } } return (~check_sum_temp) & 0xFF; } void SetFrameChecksum(M_LIN_EX_MSG *Msg) { uint8_t CheckSum = 0; uint8_t len = Msg->DataLen; if(Msg->Check) { CheckSum = MasterGetCheckSum(&Msg->PID, len + 1); } else { CheckSum = MasterGetCheckSum(Msg->Data, len); } if(len < 8) { Msg->Data[len] = CheckSum; } else { Msg->Check = CheckSum; } } void MasterSendBytes(uint8_t *pBuf, uint8_t Len) { USART_Break_Frame_Send(USARTx); while(Len--) { while(USART_Flag_Status_Get(USARTx, USART_FLAG_TXC ) == RESET); USART_Data_Send(USARTx, *pBuf++); } while(USART_Flag_Status_Get(USARTx, USART_FLAG_TXC ) == RESET); } void MasterSendFrame(M_LIN_EX_MSG Msg) { if(Msg.DataLen) { MasterSendBytes(&Msg.Sync, Msg.DataLen + 3); } else { MasterSendBytes(&Msg.Sync, 2); } } void FrameHandle(void) { uint8_t tmp_PID = M_TxMsg.PID; SetFramePID(&M_TxMsg); switch (tmp_PID) { case 0x3C://Master request frame SetFrameChecksum(&M_TxMsg); break; case 0x3D://Slave reply frame M_TxMsg.DataLen = 0; break; default: break; } MasterSendFrame(M_TxMsg); } static ErrorStatus USART_ByteReceive(uint8_t *Data, uint32_t TimeOut) { uint32_t Counter = 0; while((USART_Flag_Status_Get(USARTx, USART_FLAG_RXDNE) == RESET) && (Counter != TimeOut)) { Counter++; } if(Counter != TimeOut) { *Data = (uint8_t)USART_Data_Receive(USARTx); return SUCCESS; } else { return ERROR; } } uint32_t Master_RecData(uint8_t *pdata, uint8_t length) { int i = 0; uint8_t Data = 0; uint32_t number = 0; while(i < length) { i++; if((USART_ByteReceive(&Data, SC_RECEIVE_TIMEOUT)) == SUCCESS) { pdata[number] = Data; number++; } } return number; } ErrorStatus WaitFrameRes(uint8_t *dst_data, uint8_t length) { //int i = 0; int datalen = 0; uint8_t recv_data[16]; uint8_t CheckSum = 0; datalen = Master_RecData(recv_data, 16); if(datalen) { #if 0 log_info("recv_data:"); for(i = 1; i < datalen; i++) { log_info("0x%x\r\n", recv_data[i]); } #endif CheckSum = MasterGetCheckSum(recv_data, datalen - 1); log_info("CheckSum:0x%x\r\n", CheckSum); if(CheckSum == recv_data[datalen - 1]) { if( (datalen - 2) > length) { Buffercopy(dst_data, &recv_data[0], length); } else { Buffercopy(dst_data, &recv_data[0], datalen - 1); } return SUCCESS; } } return ERROR; } void TestMasterReqFrame(void) { int i = 0; M_LIN_EX_MSG CurLINTxMsg; CurLINTxMsg.Check = CLASSIC; CurLINTxMsg.DataLen = 8; CurLINTxMsg.Sync = 0x55; CurLINTxMsg.PID = 0x3C; for(i = 0; i < CurLINTxMsg.DataLen; i++) { CurLINTxMsg.Data[i] = 0x0F; } SetFrameMsg(&M_TxMsg, CurLINTxMsg); FrameHandle(); } void TestSlaveResFrame(void) { M_LIN_EX_MSG CurLINTxMsg; CurLINTxMsg.Check = CLASSIC; CurLINTxMsg.DataLen = 0; CurLINTxMsg.Sync = 0x55; CurLINTxMsg.PID = 0x3D; SetFrameMsg(&M_TxMsg, CurLINTxMsg); FrameHandle(); } void TestLinMaster(void) { int i = 0, count = 0; uint8_t recv_data[8]; TestMasterReqFrame(); delay_xms(20); while(count < 4) { Memset(recv_data, 0, 8); TestSlaveResFrame(); if(WaitFrameRes(recv_data, 8) == SUCCESS) { log_info("recv_data:\r\n"); for(i = 0; i < 8; i++) { log_info("recv_data[%d] = 0x%x\r\n", i, recv_data[i]); } break; } else { log_info("slave no response!!\r\n"); count++; } } } #include <stdio.h> #include "main.h" static uint8_t max_ms = 116; /** *\*\name delay_xms. *\*\fun delay program. *\*\param nms *\*\return none **/ void delay_xms(uint32_t nms) { uint16_t i; uint16_t count_1 = nms / max_ms; uint16_t count_2 = nms % max_ms; if(0 == count_1) { systick_delay_ms(nms); } else { for(i = 0; i < count_1; i++) { systick_delay_ms(max_ms); } if(count_2 != 0) { systick_delay_ms(count_2); } } } /** *\*\name Memset. *\*\fun memery set a value. *\*\param s source *\*\param c value *\*\param count number *\*\return s **/ void *Memset(void *s, s8 c, u32 count) { s8 *xs = (s8 *) s; while (count--) // clear 17byte buffer { *xs++ = c; } return s; } /** *\*\name Buffercopy. *\*\fun Compares two buffers. *\*\param pBuffer1 *\*\param pBuffer2 *\*\param buffer's length *\*\return s **/ void Buffercopy(uint8_t *dest, uint8_t *src, uint16_t BufferLength) { while (BufferLength--) { *dest = *src; dest++; src++; } } /** *\*\name main. *\*\fun Main program. *\*\param none *\*\return none **/ int main(void) { USART_InitType USART_InitStructure; log_init(); printf("\r\n test LIN master mode\r\n"); /* System Clocks Configuration */ RCC_Configuration(); /* NVIC configuration */ NVIC_Configuration(); /* Configure the GPIO ports */ GPIO_Configuration(); /* USARTx configuration ------------------------------------------------------*/ USART_InitStructure.BaudRate = 9600; USART_InitStructure.WordLength = USART_WL_8B; USART_InitStructure.StopBits = USART_STPB_1; USART_InitStructure.Parity = USART_PE_NO; USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE; USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX; /* Configure USARTx */ USART_Initializes(USARTx, &USART_InitStructure); /* Enable the USARTx LIN mode*/ USART_LIN_Break_Detect_Length_Set(USARTx,USART_LINBDL_10B); USART_LIN_Enable(USARTx); /* Enable the USARTx */ USART_Enable(USARTx); while (1) { TestLinMaster(); delay_xms(500); } } /** *\*\name RCC_Configuration. *\*\fun Configures the different system clocks. *\*\param none *\*\return none **/ void RCC_Configuration(void) { /* Enable GPIO clock */ GPIO_AHBClkCmd(USARTx_GPIO_CLK); RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO); /* Enable USARTx Clock */ USART_APBxClkCmd(USARTx_CLK); } /** *\*\name NVIC_Configuration. *\*\fun Configures the nested vectored interrupt controller. *\*\param none *\*\return none **/ void NVIC_Configuration(void) { NVIC_InitType NVIC_InitStructure; NVIC_Priority_Group_Set(NVIC_PER2_SUB2_PRIORITYGROUP); /* Enable the USARTx Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USARTx_IRQn; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Initializes(&NVIC_InitStructure); } /** *\*\name GPIO_Configuration. *\*\fun Configures the different GPIO ports. *\*\param none *\*\return none **/ void GPIO_Configuration(void) { GPIO_InitType GPIO_InitStructure; /* Initialize GPIO_InitStructure */ GPIO_Structure_Initialize(&GPIO_InitStructure); /* Configure USARTx Tx as alternate function push-pull */ GPIO_InitStructure.Pin = USARTx_TxPin; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.GPIO_Alternate = USARTx_Tx_GPIO_AF; GPIO_Peripheral_Initialize(USARTx_GPIO, &GPIO_InitStructure); /* Configure USARTx Rx as alternate function push-pull */ GPIO_InitStructure.Pin = USARTx_RxPin; GPIO_InitStructure.GPIO_Alternate = USARTx_Rx_GPIO_AF; GPIO_Peripheral_Initialize(USARTx_GPIO, &GPIO_InitStructure); }   3.2.LIN从机实现 #include "main.h" #include "lin_driver.h" LIN_STATE LinRxState = IDLE; uint8_t LINRxDataIndex = 0; LIN_EX_MSG LINRxDataBuffer[2];//双缓冲接收数据,可以减少数据出错概率 uint8_t IDType[64] = {ID_TYPE_SR}; uint8_t GotMsgFlag = 0; LIN_EX_MSG *pLINMsg; LIN_EX_MSG LINTxMsg; void LIN_SendBytes(uint8_t *pBuf, uint8_t Len) { while(Len--) { while(USART_GetFlagStatus(USARTz, USART_FLAG_TXC ) == RESET); USART_SendData(USARTz, *pBuf++); } while(USART_GetFlagStatus(USARTz, USART_FLAG_TXC ) == RESET); } uint8_t LIN_GetCheckSum(uint8_t *pData, uint8_t len) { uint16_t check_sum_temp = 0; uint8_t i; for(i = 0; i < len; i++) { check_sum_temp += pData[i]; if(check_sum_temp > 0xFF) { check_sum_temp -= 0xFF; } } return (~check_sum_temp) & 0xFF; } void LIN_SetResp(uint8_t ID, uint8_t *pData, uint8_t Len, uint8_t CheckType) { uint8_t i = 0; uint8_t CheckSum = 0; if(Len > 8) { Len = 8; } LINTxMsg.PID = GET_PID(ID); for(i = 0; i < Len; i++) { LINTxMsg.Data[i] = pData[i]; } if(CheckType) { CheckSum = LIN_GetCheckSum(&LINTxMsg.PID, Len + 1); } else { CheckSum = LIN_GetCheckSum(LINTxMsg.Data, Len); } if(Len < 8) { LINTxMsg.Data[Len] = CheckSum; } else { LINTxMsg.Check = CheckSum; } LINTxMsg.DataLen = Len; } void LIN_EX_RxAsync(uint8_t data) { switch(LinRxState) { case IDLE: break; case SYNCH: if(data == 0x55) { LINRxDataBuffer[LINRxDataIndex].Sync = 0x55; LinRxState = ID_LEN; } else { LinRxState = IDLE; } break; case ID_LEN: if(GET_PID(data) == data) { LINRxDataBuffer[LINRxDataIndex].PID = data; LINRxDataBuffer[LINRxDataIndex].DataLen = 0; if(IDType[data & 0x3F] == ID_TYPE_SR) { LinRxState = DATA_GET; } else { //接收到主机发送的帧头,从机模式发送数据 if(((LINTxMsg.PID & 0x3F) == (data & 0x3F)) && (LINTxMsg.DataLen > 0)) { LIN_SendBytes(LINTxMsg.Data, LINTxMsg.DataLen + 1); LINTxMsg.DataLen = 0; } LinRxState = IDLE; } } else { LinRxState = IDLE; } break; case DATA_GET: LINRxDataBuffer[LINRxDataIndex].Data[LINRxDataBuffer[LINRxDataIndex].DataLen] = data; LINRxDataBuffer[LINRxDataIndex].Check = data; LINRxDataBuffer[LINRxDataIndex].DataLen++; if(LINRxDataBuffer[LINRxDataIndex].DataLen >= 8) { LinRxState = CHECKSUM; } else { LinRxState = DATA_GET; } break; case CHECKSUM: LINRxDataBuffer[LINRxDataIndex].Check = data; pLINMsg = &LINRxDataBuffer[LINRxDataIndex]; GotMsgFlag = 1; LINRxDataIndex = (LINRxDataIndex + 1) % 2; LinRxState = IDLE; break; default: break; } } void LIN_IRQHandler(void) { //BREAK中断 if(USART_GetIntStatus(USARTz, USART_INT_LINBD) == SET) { USART_ClrIntPendingBit(USARTz, USART_INT_LINBD);//清除LIN间隔场检测标志位 //读状态寄存器和数据寄存器是为了清除FE标志 USARTz->STS; USARTz->DAT; LinRxState = SYNCH; return; } //接收数据中断 if (USART_GetIntStatus(USARTz, USART_INT_RXDNE) == SET) { USART_ClrIntPendingBit(USARTz, USART_INT_RXDNE); //清除接收中断标志位 if(USART_GetIntStatus(USARTz, USART_INT_FEF) == RESET) { LIN_EX_RxAsync((uint8_t)USART_ReceiveData(USARTz)); } } } /** * [url=home.php?mod=space&uid=159083]@brief[/url] 执行主机下发的命令 * @param pData 收到的数据,该函数会默认读取8字节数据 * @param pFunResp 命令响应函数指针,需要自己实现 * @retval 无 */ void BOOT_ExecutiveCommand(uint8_t *pData, FUN_RESP pFunResp) #if 1 { int i = 0; log_info("BOOT_ExecutiveCommand\r\n"); for( i = 0; i < 8; i++) { log_info("pData[%d] = %02x \r\n", i, pData[i]); pData[i] = 0x1; } pFunResp(pData, 8); } #endif #include <stdio.h> #include "main.h" /** @addtogroup N32A45X_StdPeriph_Examples * @{ */ void RCC_Configuration(void); void GPIO_Configuration(void); void NVIC_Configuration(void); static uint8_t max_ms = 116; extern uint8_t IDType[64]; extern uint8_t GotMsgFlag; extern LIN_EX_MSG *pLINMsg; void delay_xms(uint32_t nms) { uint16_t i; uint16_t count_1 = nms / max_ms; uint16_t count_2 = nms % max_ms; if(0 == count_1) { systick_delay_ms(nms); } else { for(i = 0; i < count_1; i++) { systick_delay_ms(max_ms); } if(count_2 != 0) { systick_delay_ms(count_2); } } } /** * @brief Compares two buffers. * @param pBuffer1, pBuffer2: buffers to be compared. * @param BufferLength buffer's length * [url=home.php?mod=space&uid=784970]@return[/url] PASSED: pBuffer1 identical to pBuffer2 * FAILED: pBuffer1 differs from pBuffer2 */ void Buffercopy(uint8_t *dest, uint8_t *src, uint16_t BufferLength) { while (BufferLength--) { *dest = *src; dest++; src++; } } void LIN_RespData(uint8_t *pData, uint8_t Len) { LIN_SetResp(MSG_SEND_ID, pData, Len, CHECK_TYPE); } /** * @brief Main program */ int main(void) { USART_InitType USART_InitStructure; log_init(); printf("\r\n test LIN slave mode\r\n"); /* System Clocks Configuration */ RCC_Configuration(); /* NVIC configuration */ NVIC_Configuration(); /* Configure the GPIO ports */ GPIO_Configuration(); /* USARTy and USARTz configuration ------------------------------------------------------*/ USART_InitStructure.BaudRate = 9600; USART_InitStructure.WordLength = USART_WL_8B; USART_InitStructure.StopBits = USART_STPB_1; USART_InitStructure.Parity = USART_PE_NO; USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE; USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX; /* Configure USARTy and USARTz */ USART_Init(USARTz, &USART_InitStructure); /* Enable the USARTz LIN mode*/ USART_ConfigLINBreakDetectLength(USARTz, USART_LINBDL_10B); USART_EnableLIN(USARTz, ENABLE); /* Enable USARTz Receive and Transmit interrupts */ USART_ConfigInt(USARTz, USART_INT_RXDNE, ENABLE); //USART_ConfigInt(USARTz, USART_INT_TXDE, ENABLE); USART_ConfigInt(USARTz, USART_INT_LINBD, ENABLE); /* Enable the USARTz */ USART_Enable(USARTz, ENABLE); //配置从机ID模式 IDType[MSG_RECEIVE_ID & 0x3F] = ID_TYPE_SR; IDType[MSG_SEND_ID & 0x3F] = ID_TYPE_SW; while (1) { if(GotMsgFlag) { BOOT_ExecutiveCommand(pLINMsg->Data, LIN_RespData); GotMsgFlag = 0; } } } /** * @brief Configures the different system clocks. */ void RCC_Configuration(void) { /* Enable GPIO clock */ RCC_EnableAPB2PeriphClk(USARTz_GPIO_CLK | RCC_APB2_PERIPH_AFIO, ENABLE); /* Enable USARTz Clock */ USARTz_APBxClkCmd(USARTz_CLK, ENABLE); } /** * @brief Configures the different GPIO ports. */ void GPIO_Configuration(void) { GPIO_InitType GPIO_InitStructure; /* Configure USARTz Rx as input floating */ GPIO_InitStructure.Pin = USARTz_RxPin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitPeripheral(USARTz_GPIO, &GPIO_InitStructure); /* Configure USARTz Tx as alternate function push-pull */ GPIO_InitStructure.Pin = USARTz_TxPin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitPeripheral(USARTz_GPIO, &GPIO_InitStructure); /* Configure TJA1027 SLP as ouput push-pull */ GPIO_InitStructure.Pin = SLP_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitPeripheral(SLP_GPIO, &GPIO_InitStructure); GPIO_SetBits(SLP_GPIO,SLP_Pin); #ifdef _USART2_ GPIO_ConfigPinRemap(GPIO_RMP3_USART2, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_NO_NJTRST, ENABLE); #endif #ifdef _USART4_ GPIO_ConfigPinRemap(GPIO_RMP3_UART4, ENABLE); #endif } /** * @brief Configures the nested vectored interrupt controller. */ void NVIC_Configuration(void) { NVIC_InitType NVIC_InitStructure; /* Configure the NVIC Preemption Priority Bits */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); /* Enable the USARTz Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USARTz_IRQn; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file pointer to the source file name * @param line assert_param error line source number */ void assert_failed(const uint8_t *expr, const uint8_t *file, uint32_t line) { /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* Infinite loop */ while (1) { } } #endif   4.测试 4.1.测试环境 由于没有2块N32A455开发板,所以我找了一块N32G430C8L7_STB_V1.0开发板作为LIN主机,搭配N32A455开发板作为LIN从机一起测试;但是N32G430C8L7_STB_V1.0开发板上并没有板载LIN收发芯片,所以我们还是通过交叉连接USART的RX和TX,对LIN的通讯功能进行测试,毕竟功能OK,其它只是固定的外围硬件电路,关系不大!   4.2.测试结果   5.注意事项 5.1、当使用N32A455的USART作为LIN模式通讯时,以下配置位必须全部被清零 :USART_CTRL2.STPB[1:0] 、USART_CTRL2.CLKEN 、USART_CTRL3.SCMEN 、USART_CTRL3.HDMEN 、USART_CTRL3.IRDAMEN。 5.2.在 LIN 模式下发送数据时,数据长度只能配置为 8 位。

  • 2024-02-26
  • 发表了主题帖: 【小华工控新品HC32F448】08.有工控显示需求?HC32F448帮你搞定!

    1.概述 小华H32F448系列是基于ARM Cortex-M4 32-bit RISC CPU内核的MCU,最高工作频率可达到200MHz,内核集成了FPU和DSP,实现单精度浮点算术运算,支持所有ARM单精度数据处理指令和数据类型,支持完整的DSP指令集;在支持高算力的同时,还支持外部存储器控制EXMC,在有工控显示需要的应用领域,提供更优的解决方案。   外部存储器控制器 EXMC(External Memory Controller)是一个用来访问各种片外存储器,实现数据交换的独立模块。 EXMC 通过配置可以把内部的 AMBA 协议接口转换为各种类型的专用片外存储器通信协议接口,包括 SRAM、 PSRAM、 NOR Flash 等。   2.功能列表 EXMC 基本的功能列表如下所示:   3.原理图   4.例程功能 参考示例程序,我们在网上购买了一款4.3寸,带电容触摸的TFT显示屏,对EXMC功能进行学习,通过示例程序中的功能进行测试:LCD屏幕画出正方形,触摸正方形所在区域,平移正方形位置;LCD屏幕画出圆形和红、绿、蓝三色全屏   5.示例程序  EXMC初始化配置: /** * [url=home.php?mod=space&uid=159083]@brief[/url] Initializes LCD low level. * @param None * @retval int32_t: * - LL_OK: Initialize successfully. * - LL_ERR: Initialize unsuccessfully. */ static int32_t LCD_SMC_Init(void) { __IO uint32_t u32To = 0UL; int32_t i32Ret = LL_OK; stc_exmc_smc_init_t stcSmcInit; stc_exmc_smc_chip_config_t stcChipConfig; stc_exmc_smc_timing_config_t stcTimingConfig; en_flag_status_t enChipStatus = RESET; en_flag_status_t enTimingStatus = RESET; LCD_Port_Init(); /* Enable SMC clock */ FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_SMC, ENABLE); /* Enable SMC. */ EXMC_SMC_Cmd(ENABLE); EXMC_SMC_ExitLowPower(); while (EXMC_SMC_READY != EXMC_SMC_GetStatus()) { if (u32To > SMC_MAX_TIMEOUT) { i32Ret = LL_ERR; break; } u32To++; } if (LL_OK == i32Ret) { /* Configure SMC width && CS &chip & timing. */ (void)EXMC_SMC_StructInit(&stcSmcInit); stcSmcInit.stcChipConfig.u32AddrMatch = BSP_NT35510_MATCH_ADDR; stcSmcInit.stcChipConfig.u32AddrMask = BSP_NT35510_MASK_ADDR; stcSmcInit.stcChipConfig.u32MemoryWidth = EXMC_SMC_MEMORY_WIDTH_16BIT; stcSmcInit.stcChipConfig.u32BAA = EXMC_SMC_BAA_PORT_DISABLE; stcSmcInit.stcChipConfig.u32ADV = EXMC_SMC_ADV_PORT_DISABLE; stcSmcInit.stcChipConfig.u32BLS = EXMC_SMC_BLS_SYNC_CS; stcSmcInit.stcChipConfig.u32ReadMode = EXMC_SMC_READ_ASYNC; stcSmcInit.stcChipConfig.u32WriteMode = EXMC_SMC_WRITE_ASYNC; /* EXCLK bus frequency@40MHz: 3.3V */ stcSmcInit.stcTimingConfig.u8RC = 4U; stcSmcInit.stcTimingConfig.u8WC = 2U; stcSmcInit.stcTimingConfig.u8CEOE = 1U; stcSmcInit.stcTimingConfig.u8WP = 1U; stcSmcInit.stcTimingConfig.u8TR = 1U; (void)EXMC_SMC_Init(BSP_NT35510_CHIP, &stcSmcInit); /* Set command: updateregs */ EXMC_SMC_SetCommand(BSP_NT35510_CHIP, EXMC_SMC_CMD_UPDATEREGS, 0UL, 0UL); /* Check timing status */ u32To = 0UL; while ((enChipStatus != SET) || (enTimingStatus != SET)) { (void)EXMC_SMC_GetTimingConfig(BSP_NT35510_CHIP, &stcTimingConfig); if (0 == memcmp(&stcTimingConfig, &stcSmcInit.stcTimingConfig, sizeof(stcTimingConfig))) { enTimingStatus = SET; } (void)EXMC_SMC_GetChipConfig(BSP_NT35510_CHIP, &stcChipConfig); if (0 == memcmp(&stcChipConfig, &stcSmcInit.stcChipConfig, sizeof(stcChipConfig))) { enChipStatus = SET; } if (u32To > SMC_MAX_TIMEOUT) { i32Ret = LL_ERR; break; } u32To++; } } return i32Ret; }   基于EXMC的显示屏驱动配置和基础函数实现: /** * @brief LCD delay * @param [in] u32Delay: Delay in ms * @retval None */ static void LCD_Delay(uint32_t u32Delay) { volatile uint32_t i; const uint32_t u32Cyc = 24000UL; while (u32Delay-- > 0UL) { i = u32Cyc; while (i-- > 0UL) { ; } } } /** * @brief Configure LCD NT35310 * @param [in] pstcLCD: LCD controller * @retval None */ static void LCD_NT35310_Config(stc_lcd_controller_t *pstcLCD) { NT35510_WriteReg(pstcLCD, 0xED); NT35510_WriteData(pstcLCD, 0x01); NT35510_WriteData(pstcLCD, 0xFE); NT35510_WriteReg(pstcLCD, 0xEE); NT35510_WriteData(pstcLCD, 0xDE); NT35510_WriteData(pstcLCD, 0x21); NT35510_WriteReg(pstcLCD, 0xF1); NT35510_WriteData(pstcLCD, 0x01); NT35510_WriteReg(pstcLCD, 0xDF); NT35510_WriteData(pstcLCD, 0x10); //VCOMvoltage// NT35510_WriteReg(pstcLCD, 0xC4); NT35510_WriteData(pstcLCD, 0x8F); NT35510_WriteReg(pstcLCD, 0xC6); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xE2); NT35510_WriteData(pstcLCD, 0xE2); NT35510_WriteData(pstcLCD, 0xE2); NT35510_WriteReg(pstcLCD, 0xBF); NT35510_WriteData(pstcLCD, 0xAA); NT35510_WriteReg(pstcLCD, 0xB0); NT35510_WriteData(pstcLCD, 0x0D); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x0D); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x11); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x19); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x21); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x2D); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x3D); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x5D); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x5D); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xB1); NT35510_WriteData(pstcLCD, 0x80); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x8B); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x96); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xB2); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x02); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x03); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xB3); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xB4); NT35510_WriteData(pstcLCD, 0x8B); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x96); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xA1); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xB5); NT35510_WriteData(pstcLCD, 0x02); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x03); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x04); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xB6); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xB7); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x3F); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x5E); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x64); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x8C); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xAC); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xDC); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x70); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x90); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xEB); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xDC); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xB8); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xBA); NT35510_WriteData(pstcLCD, 0x24); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xC1); NT35510_WriteData(pstcLCD, 0x20); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x54); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xFF); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xC2); NT35510_WriteData(pstcLCD, 0x0A); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x04); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xC3); NT35510_WriteData(pstcLCD, 0x3C); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x3A); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x39); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x37); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x3C); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x36); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x32); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x2F); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x2C); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x29); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x26); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x24); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x24); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x23); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x3C); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x36); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x32); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x2F); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x2C); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x29); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x26); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x24); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x24); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x23); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xC4); NT35510_WriteData(pstcLCD, 0x62); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x05); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x84); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xF0); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x18); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xA4); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x18); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x50); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x0C); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x17); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x95); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xF3); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xE6); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xC5); NT35510_WriteData(pstcLCD, 0x32); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x44); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x65); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x76); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x88); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xC6); NT35510_WriteData(pstcLCD, 0x20); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x17); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x01); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xC7); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xC8); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xC9); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xE0); NT35510_WriteData(pstcLCD, 0x16); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x1C); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x21); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x36); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x46); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x52); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x64); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x7A); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x8B); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x99); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xA8); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xB9); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xC4); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xCA); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xD2); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xD9); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xE0); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xF3); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xE1); NT35510_WriteData(pstcLCD, 0x16); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x1C); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x22); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x36); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x45); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x52); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x64); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x7A); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x8B); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x99); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xA8); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xB9); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xC4); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xCA); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xD2); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xD8); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xE0); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xF3); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xE2); NT35510_WriteData(pstcLCD, 0x05); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x0B); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x1B); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x34); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x44); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x4F); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x61); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x79); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x88); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x97); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xA6); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xB7); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xC2); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xC7); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xD1); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xD6); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xDD); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xF3); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xE3); NT35510_WriteData(pstcLCD, 0x05); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xA); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x1C); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x33); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x44); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x50); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x62); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x78); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x88); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x97); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xA6); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xB7); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xC2); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xC7); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xD1); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xD5); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xDD); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xF3); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xE4); NT35510_WriteData(pstcLCD, 0x01); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x01); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x02); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x2A); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x3C); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x4B); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x5D); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x74); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x84); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x93); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xA2); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xB3); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xBE); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xC4); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xCD); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xD3); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xDD); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xF3); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xE5); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x02); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x29); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x3C); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x4B); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x5D); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x74); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x84); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x93); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xA2); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xB3); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xBE); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xC4); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xCD); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xD3); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xDC); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xF3); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xE6); NT35510_WriteData(pstcLCD, 0x11); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x34); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x56); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x76); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x77); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x66); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x88); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x99); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xBB); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x99); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x66); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x55); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x55); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x45); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x43); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x44); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xE7); NT35510_WriteData(pstcLCD, 0x32); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x55); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x76); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x66); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x67); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x67); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x87); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x99); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xBB); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x99); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x77); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x44); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x56); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x23); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x33); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x45); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xE8); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x99); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x87); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x88); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x77); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x66); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x88); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xAA); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xBB); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x99); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x66); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x55); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x55); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x44); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x44); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x55); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xE9); NT35510_WriteData(pstcLCD, 0xAA); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0xAA); NT35510_WriteReg(pstcLCD, 0xCF); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xF0); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x50); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xF3); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0xF9); NT35510_WriteData(pstcLCD, 0x06); NT35510_WriteData(pstcLCD, 0x10); NT35510_WriteData(pstcLCD, 0x29); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0x3A); NT35510_WriteData(pstcLCD, 0x55); NT35510_WriteReg(pstcLCD, 0x11); LCD_Delay(100); NT35510_WriteReg(pstcLCD, 0x29); NT35510_WriteReg(pstcLCD, 0x35); NT35510_WriteData(pstcLCD, 0x00); NT35510_WriteReg(pstcLCD, 0x51); NT35510_WriteData(pstcLCD, 0xFF); NT35510_WriteReg(pstcLCD, 0x53); NT35510_WriteData(pstcLCD, 0x2C); NT35510_WriteReg(pstcLCD, 0x55); NT35510_WriteData(pstcLCD, 0x82); NT35510_WriteReg(pstcLCD, 0x2c); } /** * @brief Configure LCD NT35510 * @param [in] pstcLCD: LCD controller * @retval None */ static void LCD_NT35510_Config(stc_lcd_controller_t *pstcLCD) { /* Config LCD */ NT35510_WriteRegData(pstcLCD, 0xF000U, 0x55U); NT35510_WriteRegData(pstcLCD, 0xF001U, 0xAAU); NT35510_WriteRegData(pstcLCD, 0xF002U, 0x52U); NT35510_WriteRegData(pstcLCD, 0xF003U, 0x08U); NT35510_WriteRegData(pstcLCD, 0xF004U, 0x01U); /* AVDD Set AVDD 5.2V */ NT35510_WriteRegData(pstcLCD, 0xB000U, 0x0DU); NT35510_WriteRegData(pstcLCD, 0xB001U, 0x0DU); NT35510_WriteRegData(pstcLCD, 0xB002U, 0x0DU); /* AVDD ratio */ NT35510_WriteRegData(pstcLCD, 0xB600U, 0x34U); NT35510_WriteRegData(pstcLCD, 0xB601U, 0x34U); NT35510_WriteRegData(pstcLCD, 0xB602U, 0x34U); /* AVEE -5.2V */ NT35510_WriteRegData(pstcLCD, 0xB100U, 0x0DU); NT35510_WriteRegData(pstcLCD, 0xB101U, 0x0DU); NT35510_WriteRegData(pstcLCD, 0xB102U, 0x0DU); /* AVEE ratio */ NT35510_WriteRegData(pstcLCD, 0xB700U, 0x34U); NT35510_WriteRegData(pstcLCD, 0xB701U, 0x34U); NT35510_WriteRegData(pstcLCD, 0xB702U, 0x34U); /* VCL -2.5V */ NT35510_WriteRegData(pstcLCD, 0xB200U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xB201U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xB202U, 0x00U); /* VCL ratio */ NT35510_WriteRegData(pstcLCD, 0xB800U, 0x24U); NT35510_WriteRegData(pstcLCD, 0xB801U, 0x24U); NT35510_WriteRegData(pstcLCD, 0xB802U, 0x24U); /* VGH 15V (Free pump) */ NT35510_WriteRegData(pstcLCD, 0xBF00U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xB300U, 0x0FU); NT35510_WriteRegData(pstcLCD, 0xB301U, 0x0FU); NT35510_WriteRegData(pstcLCD, 0xB302U, 0x0FU); /* VGH ratio */ NT35510_WriteRegData(pstcLCD, 0xB900U, 0x34U); NT35510_WriteRegData(pstcLCD, 0xB901U, 0x34U); NT35510_WriteRegData(pstcLCD, 0xB902U, 0x34U); /* VGL_REG -10V */ NT35510_WriteRegData(pstcLCD, 0xB500U, 0x08U); NT35510_WriteRegData(pstcLCD, 0xB501U, 0x08U); NT35510_WriteRegData(pstcLCD, 0xB502U, 0x08U); NT35510_WriteRegData(pstcLCD, 0xC200U, 0x03U); /* VGLX ratio */ NT35510_WriteRegData(pstcLCD, 0xBA00U, 0x24U); NT35510_WriteRegData(pstcLCD, 0xBA01U, 0x24U); NT35510_WriteRegData(pstcLCD, 0xBA02U, 0x24U); /* VGMP/VGSP 4.5V/0V */ NT35510_WriteRegData(pstcLCD, 0xBC00U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xBC01U, 0x78U); NT35510_WriteRegData(pstcLCD, 0xBC02U, 0x00U); /* VGMN/VGSN -4.5V/0V */ NT35510_WriteRegData(pstcLCD, 0xBD00U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xBD01U, 0x78U); NT35510_WriteRegData(pstcLCD, 0xBD02U, 0x00U); /* VCOM */ NT35510_WriteRegData(pstcLCD, 0xBE00U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xBE01U, 0x64U); /* Gamma Setting */ NT35510_WriteRegData(pstcLCD, 0xD100U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD101U, 0x33U); NT35510_WriteRegData(pstcLCD, 0xD102U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD103U, 0x34U); NT35510_WriteRegData(pstcLCD, 0xD104U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD105U, 0x3AU); NT35510_WriteRegData(pstcLCD, 0xD106U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD107U, 0x4AU); NT35510_WriteRegData(pstcLCD, 0xD108U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD109U, 0x5CU); NT35510_WriteRegData(pstcLCD, 0xD10AU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD10BU, 0x81U); NT35510_WriteRegData(pstcLCD, 0xD10CU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD10DU, 0xA6U); NT35510_WriteRegData(pstcLCD, 0xD10EU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD10FU, 0xE5U); NT35510_WriteRegData(pstcLCD, 0xD110U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD111U, 0x13U); NT35510_WriteRegData(pstcLCD, 0xD112U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD113U, 0x54U); NT35510_WriteRegData(pstcLCD, 0xD114U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD115U, 0x82U); NT35510_WriteRegData(pstcLCD, 0xD116U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD117U, 0xCAU); NT35510_WriteRegData(pstcLCD, 0xD118U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD119U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD11AU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD11BU, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD11CU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD11DU, 0x34U); NT35510_WriteRegData(pstcLCD, 0xD11EU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD11FU, 0x67U); NT35510_WriteRegData(pstcLCD, 0xD120U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD121U, 0x84U); NT35510_WriteRegData(pstcLCD, 0xD122U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD123U, 0xA4U); NT35510_WriteRegData(pstcLCD, 0xD124U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD125U, 0xB7U); NT35510_WriteRegData(pstcLCD, 0xD126U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD127U, 0xCFU); NT35510_WriteRegData(pstcLCD, 0xD128U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD129U, 0xDEU); NT35510_WriteRegData(pstcLCD, 0xD12AU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD12BU, 0xF2U); NT35510_WriteRegData(pstcLCD, 0xD12CU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD12DU, 0xFEU); NT35510_WriteRegData(pstcLCD, 0xD12EU, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD12FU, 0x10U); NT35510_WriteRegData(pstcLCD, 0xD130U, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD131U, 0x33U); NT35510_WriteRegData(pstcLCD, 0xD132U, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD133U, 0x6DU); NT35510_WriteRegData(pstcLCD, 0xD200U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD201U, 0x33U); NT35510_WriteRegData(pstcLCD, 0xD202U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD203U, 0x34U); NT35510_WriteRegData(pstcLCD, 0xD204U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD205U, 0x3AU); NT35510_WriteRegData(pstcLCD, 0xD206U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD207U, 0x4AU); NT35510_WriteRegData(pstcLCD, 0xD208U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD209U, 0x5CU); NT35510_WriteRegData(pstcLCD, 0xD20AU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD20BU, 0x81U); NT35510_WriteRegData(pstcLCD, 0xD20CU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD20DU, 0xA6U); NT35510_WriteRegData(pstcLCD, 0xD20EU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD20FU, 0xE5U); NT35510_WriteRegData(pstcLCD, 0xD210U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD211U, 0x13U); NT35510_WriteRegData(pstcLCD, 0xD212U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD213U, 0x54U); NT35510_WriteRegData(pstcLCD, 0xD214U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD215U, 0x82U); NT35510_WriteRegData(pstcLCD, 0xD216U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD217U, 0xCAU); NT35510_WriteRegData(pstcLCD, 0xD218U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD219U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD21AU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD21BU, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD21CU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD21DU, 0x34U); NT35510_WriteRegData(pstcLCD, 0xD21EU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD21FU, 0x67U); NT35510_WriteRegData(pstcLCD, 0xD220U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD221U, 0x84U); NT35510_WriteRegData(pstcLCD, 0xD222U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD223U, 0xA4U); NT35510_WriteRegData(pstcLCD, 0xD224U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD225U, 0xB7U); NT35510_WriteRegData(pstcLCD, 0xD226U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD227U, 0xCFU); NT35510_WriteRegData(pstcLCD, 0xD228U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD229U, 0xDEU); NT35510_WriteRegData(pstcLCD, 0xD22AU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD22BU, 0xF2U); NT35510_WriteRegData(pstcLCD, 0xD22CU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD22DU, 0xFEU); NT35510_WriteRegData(pstcLCD, 0xD22EU, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD22FU, 0x10U); NT35510_WriteRegData(pstcLCD, 0xD230U, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD231U, 0x33U); NT35510_WriteRegData(pstcLCD, 0xD232U, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD233U, 0x6DU); NT35510_WriteRegData(pstcLCD, 0xD300U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD301U, 0x33U); NT35510_WriteRegData(pstcLCD, 0xD302U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD303U, 0x34U); NT35510_WriteRegData(pstcLCD, 0xD304U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD305U, 0x3AU); NT35510_WriteRegData(pstcLCD, 0xD306U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD307U, 0x4AU); NT35510_WriteRegData(pstcLCD, 0xD308U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD309U, 0x5CU); NT35510_WriteRegData(pstcLCD, 0xD30AU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD30BU, 0x81U); NT35510_WriteRegData(pstcLCD, 0xD30CU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD30DU, 0xA6U); NT35510_WriteRegData(pstcLCD, 0xD30EU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD30FU, 0xE5U); NT35510_WriteRegData(pstcLCD, 0xD310U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD311U, 0x13U); NT35510_WriteRegData(pstcLCD, 0xD312U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD313U, 0x54U); NT35510_WriteRegData(pstcLCD, 0xD314U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD315U, 0x82U); NT35510_WriteRegData(pstcLCD, 0xD316U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD317U, 0xCAU); NT35510_WriteRegData(pstcLCD, 0xD318U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD319U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD31AU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD31BU, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD31CU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD31DU, 0x34U); NT35510_WriteRegData(pstcLCD, 0xD31EU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD31FU, 0x67U); NT35510_WriteRegData(pstcLCD, 0xD320U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD321U, 0x84U); NT35510_WriteRegData(pstcLCD, 0xD322U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD323U, 0xA4U); NT35510_WriteRegData(pstcLCD, 0xD324U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD325U, 0xB7U); NT35510_WriteRegData(pstcLCD, 0xD326U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD327U, 0xCFU); NT35510_WriteRegData(pstcLCD, 0xD328U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD329U, 0xDEU); NT35510_WriteRegData(pstcLCD, 0xD32AU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD32BU, 0xF2U); NT35510_WriteRegData(pstcLCD, 0xD32CU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD32DU, 0xFEU); NT35510_WriteRegData(pstcLCD, 0xD32EU, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD32FU, 0x10U); NT35510_WriteRegData(pstcLCD, 0xD330U, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD331U, 0x33U); NT35510_WriteRegData(pstcLCD, 0xD332U, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD333U, 0x6DU); NT35510_WriteRegData(pstcLCD, 0xD400U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD401U, 0x33U); NT35510_WriteRegData(pstcLCD, 0xD402U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD403U, 0x34U); NT35510_WriteRegData(pstcLCD, 0xD404U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD405U, 0x3AU); NT35510_WriteRegData(pstcLCD, 0xD406U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD407U, 0x4AU); NT35510_WriteRegData(pstcLCD, 0xD408U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD409U, 0x5CU); NT35510_WriteRegData(pstcLCD, 0xD40AU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD40BU, 0x81U); NT35510_WriteRegData(pstcLCD, 0xD40CU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD40DU, 0xA6U); NT35510_WriteRegData(pstcLCD, 0xD40EU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD40FU, 0xE5U); NT35510_WriteRegData(pstcLCD, 0xD410U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD411U, 0x13U); NT35510_WriteRegData(pstcLCD, 0xD412U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD413U, 0x54U); NT35510_WriteRegData(pstcLCD, 0xD414U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD415U, 0x82U); NT35510_WriteRegData(pstcLCD, 0xD416U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD417U, 0xCAU); NT35510_WriteRegData(pstcLCD, 0xD418U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD419U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD41AU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD41BU, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD41CU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD41DU, 0x34U); NT35510_WriteRegData(pstcLCD, 0xD41EU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD41FU, 0x67U); NT35510_WriteRegData(pstcLCD, 0xD420U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD421U, 0x84U); NT35510_WriteRegData(pstcLCD, 0xD422U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD423U, 0xA4U); NT35510_WriteRegData(pstcLCD, 0xD424U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD425U, 0xB7U); NT35510_WriteRegData(pstcLCD, 0xD426U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD427U, 0xCFU); NT35510_WriteRegData(pstcLCD, 0xD428U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD429U, 0xDEU); NT35510_WriteRegData(pstcLCD, 0xD42AU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD42BU, 0xF2U); NT35510_WriteRegData(pstcLCD, 0xD42CU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD42DU, 0xFEU); NT35510_WriteRegData(pstcLCD, 0xD42EU, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD42FU, 0x10U); NT35510_WriteRegData(pstcLCD, 0xD430U, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD431U, 0x33U); NT35510_WriteRegData(pstcLCD, 0xD432U, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD433U, 0x6DU); NT35510_WriteRegData(pstcLCD, 0xD500U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD501U, 0x33U); NT35510_WriteRegData(pstcLCD, 0xD502U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD503U, 0x34U); NT35510_WriteRegData(pstcLCD, 0xD504U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD505U, 0x3AU); NT35510_WriteRegData(pstcLCD, 0xD506U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD507U, 0x4AU); NT35510_WriteRegData(pstcLCD, 0xD508U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD509U, 0x5CU); NT35510_WriteRegData(pstcLCD, 0xD50AU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD50BU, 0x81U); NT35510_WriteRegData(pstcLCD, 0xD50CU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD50DU, 0xA6U); NT35510_WriteRegData(pstcLCD, 0xD50EU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD50FU, 0xE5U); NT35510_WriteRegData(pstcLCD, 0xD510U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD511U, 0x13U); NT35510_WriteRegData(pstcLCD, 0xD512U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD513U, 0x54U); NT35510_WriteRegData(pstcLCD, 0xD514U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD515U, 0x82U); NT35510_WriteRegData(pstcLCD, 0xD516U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD517U, 0xCAU); NT35510_WriteRegData(pstcLCD, 0xD518U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD519U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD51AU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD51BU, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD51CU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD51DU, 0x34U); NT35510_WriteRegData(pstcLCD, 0xD51EU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD51FU, 0x67U); NT35510_WriteRegData(pstcLCD, 0xD520U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD521U, 0x84U); NT35510_WriteRegData(pstcLCD, 0xD522U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD523U, 0xA4U); NT35510_WriteRegData(pstcLCD, 0xD524U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD525U, 0xB7U); NT35510_WriteRegData(pstcLCD, 0xD526U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD527U, 0xCFU); NT35510_WriteRegData(pstcLCD, 0xD528U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD529U, 0xDEU); NT35510_WriteRegData(pstcLCD, 0xD52AU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD52BU, 0xF2U); NT35510_WriteRegData(pstcLCD, 0xD52CU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD52DU, 0xFEU); NT35510_WriteRegData(pstcLCD, 0xD52EU, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD52FU, 0x10U); NT35510_WriteRegData(pstcLCD, 0xD530U, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD531U, 0x33U); NT35510_WriteRegData(pstcLCD, 0xD532U, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD533U, 0x6DU); NT35510_WriteRegData(pstcLCD, 0xD600U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD601U, 0x33U); NT35510_WriteRegData(pstcLCD, 0xD602U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD603U, 0x34U); NT35510_WriteRegData(pstcLCD, 0xD604U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD605U, 0x3AU); NT35510_WriteRegData(pstcLCD, 0xD606U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD607U, 0x4AU); NT35510_WriteRegData(pstcLCD, 0xD608U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD609U, 0x5CU); NT35510_WriteRegData(pstcLCD, 0xD60AU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD60BU, 0x81U); NT35510_WriteRegData(pstcLCD, 0xD60CU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD60DU, 0xA6U); NT35510_WriteRegData(pstcLCD, 0xD60EU, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD60FU, 0xE5U); NT35510_WriteRegData(pstcLCD, 0xD610U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD611U, 0x13U); NT35510_WriteRegData(pstcLCD, 0xD612U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD613U, 0x54U); NT35510_WriteRegData(pstcLCD, 0xD614U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD615U, 0x82U); NT35510_WriteRegData(pstcLCD, 0xD616U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD617U, 0xCAU); NT35510_WriteRegData(pstcLCD, 0xD618U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD619U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xD61AU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD61BU, 0x01U); NT35510_WriteRegData(pstcLCD, 0xD61CU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD61DU, 0x34U); NT35510_WriteRegData(pstcLCD, 0xD61EU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD61FU, 0x67U); NT35510_WriteRegData(pstcLCD, 0xD620U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD621U, 0x84U); NT35510_WriteRegData(pstcLCD, 0xD622U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD623U, 0xA4U); NT35510_WriteRegData(pstcLCD, 0xD624U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD625U, 0xB7U); NT35510_WriteRegData(pstcLCD, 0xD626U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD627U, 0xCFU); NT35510_WriteRegData(pstcLCD, 0xD628U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD629U, 0xDEU); NT35510_WriteRegData(pstcLCD, 0xD62AU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD62BU, 0xF2U); NT35510_WriteRegData(pstcLCD, 0xD62CU, 0x02U); NT35510_WriteRegData(pstcLCD, 0xD62DU, 0xFEU); NT35510_WriteRegData(pstcLCD, 0xD62EU, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD62FU, 0x10U); NT35510_WriteRegData(pstcLCD, 0xD630U, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD631U, 0x33U); NT35510_WriteRegData(pstcLCD, 0xD632U, 0x03U); NT35510_WriteRegData(pstcLCD, 0xD633U, 0x6DU); /* LV2 Page 0 enable */ NT35510_WriteRegData(pstcLCD, 0xF000U, 0x55U); NT35510_WriteRegData(pstcLCD, 0xF001U, 0xAAU); NT35510_WriteRegData(pstcLCD, 0xF002U, 0x52U); NT35510_WriteRegData(pstcLCD, 0xF003U, 0x08U); NT35510_WriteRegData(pstcLCD, 0xF004U, 0x00U); /* Display control */ NT35510_WriteRegData(pstcLCD, 0xB100U, 0xCCU); NT35510_WriteRegData(pstcLCD, 0xB101U, 0x00U); /* Source hold time */ NT35510_WriteRegData(pstcLCD, 0xB600U, 0x05U); /* Gate EQ control */ NT35510_WriteRegData(pstcLCD, 0xB700U, 0x70U); NT35510_WriteRegData(pstcLCD, 0xB701U, 0x70U); /* Source EQ control (Mode 2) */ NT35510_WriteRegData(pstcLCD, 0xB800U, 0x01U); NT35510_WriteRegData(pstcLCD, 0xB801U, 0x03U); NT35510_WriteRegData(pstcLCD, 0xB802U, 0x03U); NT35510_WriteRegData(pstcLCD, 0xB803U, 0x03U); /* Inversion mode (2-dot) */ NT35510_WriteRegData(pstcLCD, 0xBC00U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xBC01U, 0x00U); NT35510_WriteRegData(pstcLCD, 0xBC02U, 0x00U); /* Timing control 4H w/ 4-delay */ NT35510_WriteRegData(pstcLCD, 0xC900U, 0xD0U); NT35510_WriteRegData(pstcLCD, 0xC901U, 0x02U); NT35510_WriteRegData(pstcLCD, 0xC902U, 0x50U); NT35510_WriteRegData(pstcLCD, 0xC903U, 0x50U); NT35510_WriteRegData(pstcLCD, 0xC904U, 0x50U); NT35510_WriteRegData(pstcLCD, 0x3500U, 0x00U); NT35510_WriteRegData(pstcLCD, 0x3A00U, 0x55U); /* 16-bit/pixel */ NT35510_WriteReg(pstcLCD, 0x1100U); LCD_Delay(120UL); NT35510_WriteReg(pstcLCD, 0x2900U); } /** * @} */ /** * @defgroup NT35510_Global_Functions NT35510 Global Functions * @{ */ /** * @brief Initialize LCD device. * @param [in] pstcLCD: LCD controller * @retval None */ void NT35510_Init(stc_lcd_controller_t *pstcLCD) { uint16_t u16ID; if (NULL != pstcLCD) { /* NOP */ NT35510_WriteRegData(pstcLCD, 0x0000U, 0x00U); /* Read ID */ u16ID = NT35510_ReadID(pstcLCD); if (0x5310U == u16ID) { LCD_NT35310_Config(pstcLCD); m_stcLcdDevice.u16Width = 320U; m_stcLcdDevice.u16Height = 480U; m_stcLcdDevice.u16WRamCmd = 0x2CU; m_stcLcdDevice.u16SetXCmd = 0x2AU; m_stcLcdDevice.u16SetYCmd = 0x2BU; } else if (0x5510U == u16ID) { LCD_NT35510_Config(pstcLCD); m_stcLcdDevice.u16Width = 480U; m_stcLcdDevice.u16Height = 800U; m_stcLcdDevice.u16WRamCmd = 0x2C00U; m_stcLcdDevice.u16SetXCmd = 0x2A00U; m_stcLcdDevice.u16SetYCmd = 0x2B00U; } else { /* Unsupported LCD */ } m_stcLcdDevice.u16ID = u16ID; NT35510_SetDisplayDir(pstcLCD, LCD_DISPLAY_VERTICAL); /* Set cursor */ NT35510_SetCursor(pstcLCD, 0U, 0U); /* Prepare to write to LCD RAM */ NT35510_PrepareWriteRAM(pstcLCD); } } /** * @brief Write data on LCD data register. * @param [in] pstcLCD: LCD controller [url=home.php?mod=space&uid=1064992]@ref[/url] stc_lcd_controller_t structure. * @param [in] u16Data: Data to be written * @retval None */ void NT35510_WriteData(stc_lcd_controller_t *pstcLCD, uint16_t u16Data) { if (NULL != pstcLCD) { pstcLCD->u16RAM = u16Data; } } /** * @brief Write register on LCD register. * @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure. * @param [in] u16Reg: Address of the selected register. * @retval None */ void NT35510_WriteReg(stc_lcd_controller_t *pstcLCD, uint16_t u16Reg) { if (NULL != pstcLCD) { pstcLCD->u16REG = u16Reg; } } /** * @brief Read data from LCD data register. * @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure. * @retval Read data. */ uint16_t NT35510_ReadData(stc_lcd_controller_t *pstcLCD) { uint16_t u16Val = 0U; if (NULL != pstcLCD) { u16Val = pstcLCD->u16RAM; } return u16Val; } /** * @brief Write to the selected LCD register. * @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure. * @param [in] u16Reg: Address of the selected register. * @param [in] u16Data: Data to be written * @retval None */ void NT35510_WriteRegData(stc_lcd_controller_t *pstcLCD, uint16_t u16Reg, uint16_t u16Data) { if (NULL != pstcLCD) { /* Write 16-bit index */ pstcLCD->u16REG = u16Reg; /* Write 16-bit Reg */ pstcLCD->u16RAM = u16Data; } } /** * @brief Read the selected LCD register. * @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure. * @param [in] u16Reg: Address of the selected register. * @retval Register value */ uint16_t NT35510_ReadRegData(stc_lcd_controller_t *pstcLCD, uint16_t u16Reg) { uint16_t u16Val = 0U; if (NULL != pstcLCD) { /* Write 16-bit index*/ pstcLCD->u16REG = u16Reg; u16Val = pstcLCD->u16RAM; } return u16Val; } /** * @brief Read LCD ID. * @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure. * @retval LCD Register Value. */ uint16_t NT35510_ReadID(stc_lcd_controller_t *pstcLCD) { uint16_t u16ID = 0U; if (NULL != pstcLCD) { /* Try to read ID: 0x9341 */ NT35510_WriteReg(pstcLCD, 0xD3U); (void)NT35510_ReadData(pstcLCD); /* dummy read */ (void)NT35510_ReadData(pstcLCD); /* read: 0x00 */ u16ID = NT35510_ReadData(pstcLCD) << 8; /* read: 0x93 */ u16ID |= NT35510_ReadData(pstcLCD); /* read: 0x41 */ if (u16ID != 0x9341U) { /* Try to read ID: 0x8552 */ NT35510_WriteReg(pstcLCD, 0x04U); (void)NT35510_ReadData(pstcLCD); /* dummy read */ (void)NT35510_ReadData(pstcLCD); /* read: 0x85 */ u16ID = NT35510_ReadData(pstcLCD) << 8; /* read: 0x85 */ u16ID |= NT35510_ReadData(pstcLCD); /* read: 0x41 */ if (u16ID == 0x8552U) { u16ID = 0x7789U; /* ID convert to: 0x7789 */ } else { /* Try to read ID: 0x5310 (NT35310) */ NT35510_WriteReg(pstcLCD, 0xD4U); (void)NT35510_ReadData(pstcLCD); /* dummy read */ (void)NT35510_ReadData(pstcLCD); /* read: 0x01 */ u16ID = NT35510_ReadData(pstcLCD) << 8; /* read: 0x53 */ u16ID |= NT35510_ReadData(pstcLCD); /* read: 0x10 */ if (u16ID != 0x5310U) { /* Try to read ID: 0x008000 (NT35510) */ NT35510_WriteReg(pstcLCD, 0xDA00); (void)NT35510_ReadData(pstcLCD); /* read 0xDA00: 0x0000 */ NT35510_WriteReg(pstcLCD, 0xDB00U); u16ID = NT35510_ReadData(pstcLCD) << 8; /* read 0xDB00: 0x0080 */ NT35510_WriteReg(pstcLCD, 0xDC00U); u16ID |= NT35510_ReadData(pstcLCD); /* read 0xDC00: 0x0000 */ /* Read ID: ID=008000H (5510H) */ if (u16ID == 0x008000UL) { u16ID = 0x5510U; /* ID convert to: 0x5510 */ } else { u16ID = 0U; /* Unsupported LCD */ } } } } } return u16ID; } /** * @brief Enable the Display. * @param [in] pstcLCD: LCD controller * @retval None */ void NT35510_DisplayOn(stc_lcd_controller_t *pstcLCD) { if (NULL != pstcLCD) { if (m_stcLcdDevice.u16ID == 0x5510U) { NT35510_WriteReg(pstcLCD, 0x2900U); /* 5510 */ } else { NT35510_WriteReg(pstcLCD, 0x29U); /* 9341/5310/1963/7789 */ } } } /** * @brief Disable the Display. * @param [in] pstcLCD: LCD controller * @retval None */ void NT35510_DisplayOff(stc_lcd_controller_t *pstcLCD) { if (NULL != pstcLCD) { if (m_stcLcdDevice.u16ID == 0x5510U) { NT35510_WriteReg(pstcLCD, 0x2800U); /* 5510 */ } else { NT35510_WriteReg(pstcLCD, 0x28U); /* 9341/5310/1963/7789 */ } } } /** * @brief Get LCD PIXEL WIDTH. * @param None * @retval LCD PIXEL WIDTH. */ uint16_t NT35510_GetPixelWidth(void) { return m_stcLcdDevice.u16Width; } /** * @brief Get LCD PIXEL HEIGHT. * @param None * @retval LCD PIXEL HEIGHT. */ uint16_t NT35510_GetPixelHeight(void) { return m_stcLcdDevice.u16Height; } /** * @brief Set scan direction. * @param [in] pstcLCD: LCD controller * @param [in] u16Dir: Scan direction * This parameter can be one of the following values: * [url=home.php?mod=space&uid=1238002]@arg[/url] LCD_SCAN_DIR_L2R_U2D: From left to right && from up to down * @arg LCD_SCAN_DIR_L2R_D2U: From left to right && from down to up * @arg LCD_SCAN_DIR_R2L_U2D: From right to left && from up to down * @arg LCD_SCAN_DIR_R2L_D2U: From right to left && from down to up * @arg LCD_SCAN_DIR_U2D_L2R: From up to down && from left to right * @arg LCD_SCAN_DIR_U2D_R2L: From up to down && from right to left * @arg LCD_SCAN_DIR_D2U_L2R: From down to up && from left to right * @arg LCD_SCAN_DIR_D2U_R2L: From down to up && from right to left * @retval None */ void NT35510_SetScanDir(stc_lcd_controller_t *pstcLCD, uint16_t u16Dir) { uint16_t u16Temp; uint16_t dirreg; uint16_t regval = 0U; if (NULL != pstcLCD) { /* when display dir is VERTICAL, 1963 IC change scan-direction, other IC don't change when display dir is HORIZONTAL, 1963 IC don't change scan-direction, other IC change */ if (((0U == m_stcLcdDevice.u16Dir) && (m_stcLcdDevice.u16ID == 0x1963U)) || \ ((1U == m_stcLcdDevice.u16Dir) && (m_stcLcdDevice.u16ID != 0x1963U))) { if (0U == u16Dir) { u16Dir = 6U; } else if (1U == u16Dir) { u16Dir = 7U; } else if (2U == u16Dir) { u16Dir = 4U; } else if (3UL == u16Dir) { u16Dir = 5U; } else if (4U == u16Dir) { u16Dir = 1U; } else if (5U == u16Dir) { u16Dir = 0U; } else if (6U == u16Dir) { u16Dir = 3U; } else if (7U == u16Dir) { u16Dir = 2U; } else { u16Dir = 6U; } } switch (u16Dir) { case LCD_SCAN_DIR_L2R_U2D: regval |= ((0U << 7) | (0U << 6) | (0U << 5)); break; case LCD_SCAN_DIR_L2R_D2U: regval |= ((1U << 7) | (0U << 6) | (0U << 5)); break; case LCD_SCAN_DIR_R2L_U2D: regval |= ((0U << 7) | (1U << 6) | (0U << 5)); break; case LCD_SCAN_DIR_R2L_D2U: regval |= ((1U << 7) | (1U << 6) | (0U << 5)); break; case LCD_SCAN_DIR_U2D_L2R: regval |= ((0U << 7) | (0U << 6) | (1U << 5)); break; case LCD_SCAN_DIR_U2D_R2L: regval |= ((0U << 7) | (1U << 6) | (1U << 5)); break; case LCD_SCAN_DIR_D2U_L2R: regval |= ((1U << 7) | (0U << 6) | (1U << 5)); break; case LCD_SCAN_DIR_D2U_R2L: regval |= ((1U << 7) | (1U << 6) | (1U << 5)); break; default: break; } if (0x5510U == m_stcLcdDevice.u16ID) { dirreg = 0x3600U; } else { dirreg = 0x36U; } /* 0x9341 & 0x7789 set BGR bit */ if ((0x9341U == m_stcLcdDevice.u16ID) || (0x7789U == m_stcLcdDevice.u16ID)) { regval |= 0x08U; } NT35510_WriteRegData(pstcLCD, dirreg, regval); /* 1963 don't handle coordinate */ if (m_stcLcdDevice.u16ID != 0x1963U) { if ((regval & 0x20U) > 0U) { /* swap X,Y */ if (m_stcLcdDevice.u16Width < m_stcLcdDevice.u16Height) { u16Temp = m_stcLcdDevice.u16Width; m_stcLcdDevice.u16Width = m_stcLcdDevice.u16Height; m_stcLcdDevice.u16Height = u16Temp; } } else { /* swap X,Y */ if (m_stcLcdDevice.u16Width > m_stcLcdDevice.u16Height) { u16Temp = m_stcLcdDevice.u16Width; m_stcLcdDevice.u16Width = m_stcLcdDevice.u16Height; m_stcLcdDevice.u16Height = u16Temp; } } } /* Set display window size */ if (0x5510U == m_stcLcdDevice.u16ID) { NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetXCmd); NT35510_WriteData(pstcLCD, 0U); NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetXCmd + 1U); NT35510_WriteData(pstcLCD, 0U); NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetXCmd + 2U); NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Width - 1U) >> 8U); NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetXCmd + 3U); NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Width - 1U) & 0xFFU); NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetYCmd); NT35510_WriteData(pstcLCD, 0U); NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetYCmd + 1U); NT35510_WriteData(pstcLCD, 0U); NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetYCmd + 2U); NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Height - 1U) >> 8U); NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetYCmd + 3U); NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Height - 1U) & 0xFFU); } else { NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetYCmd); NT35510_WriteData(pstcLCD, 0U); NT35510_WriteData(pstcLCD, 0U); NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Width - 1U) >> 8); NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Width - 1U) & 0xFFU); NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetYCmd); NT35510_WriteData(pstcLCD, 0U); NT35510_WriteData(pstcLCD, 0U); NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Height - 1U) >> 8); NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Height - 1U) & 0xFFU); } } } /** * @brief Set screen direction. * @param [in] pstcLCD: LCD controller * @param [in] u16Dir: Screen direction * This parameter can be one of the following values: * @arg LCD_DISPLAY_VERTICAL: LCD vertical display * @arg LCD_DISPLAY_HORIZONTAL: LCD horizontal display * @retval None */ void NT35510_SetDisplayDir(stc_lcd_controller_t *pstcLCD, uint16_t u16Dir) { if (NULL != pstcLCD) { if (LCD_DISPLAY_VERTICAL == u16Dir) { /* Vertical */ if (0x1963U == m_stcLcdDevice.u16ID) { m_stcLcdDevice.u16WRamCmd = 0x2CU; m_stcLcdDevice.u16SetXCmd = 0x2BU; m_stcLcdDevice.u16SetYCmd = 0x2AU; m_stcLcdDevice.u16Width = 480U; m_stcLcdDevice.u16Height = 800U; } else if (0x5510U == m_stcLcdDevice.u16ID) { /* NT35510 */ m_stcLcdDevice.u16WRamCmd = 0x2C00U; m_stcLcdDevice.u16SetXCmd = 0x2A00U; m_stcLcdDevice.u16SetYCmd = 0x2B00U; m_stcLcdDevice.u16Width = 480U; m_stcLcdDevice.u16Height = 800U; } else { /* NT35310 / 9341 / 5310 / 7789 etc */ m_stcLcdDevice.u16WRamCmd = 0x2CU; m_stcLcdDevice.u16SetXCmd = 0x2AU; m_stcLcdDevice.u16SetYCmd = 0x2BU; if (0x5310U == m_stcLcdDevice.u16ID) { /* NT35310 */ m_stcLcdDevice.u16Width = 320U; m_stcLcdDevice.u16Height = 480U; } else { m_stcLcdDevice.u16Width = 240U; m_stcLcdDevice.u16Height = 320U; } } } else { /* Horizontal */ if (0x1963U == m_stcLcdDevice.u16ID) { m_stcLcdDevice.u16WRamCmd = 0x2CU; m_stcLcdDevice.u16SetXCmd = 0x2AU; m_stcLcdDevice.u16SetYCmd = 0x2BU; m_stcLcdDevice.u16Width = 800U; m_stcLcdDevice.u16Height = 480U; } else if (0x5510U == m_stcLcdDevice.u16ID) { /* NT35510 */ m_stcLcdDevice.u16WRamCmd = 0x2C00U; m_stcLcdDevice.u16SetXCmd = 0x2A00U; m_stcLcdDevice.u16SetYCmd = 0x2B00U; m_stcLcdDevice.u16Width = 800U; m_stcLcdDevice.u16Height = 480U; } else { /* NT35310 / 9341 / 5310 / 7789 etc */ m_stcLcdDevice.u16WRamCmd = 0x2CU; m_stcLcdDevice.u16SetXCmd = 0x2AU; m_stcLcdDevice.u16SetYCmd = 0x2BU; if (0x5310U == m_stcLcdDevice.u16ID) { /* NT35310 */ m_stcLcdDevice.u16Width = 480U; m_stcLcdDevice.u16Height = 320U; } else { m_stcLcdDevice.u16Width = 320U; m_stcLcdDevice.u16Height = 240U; } } } m_stcLcdDevice.u16Dir = u16Dir; NT35510_SetScanDir(pstcLCD, LCD_SCAN_DIR); } } /** * @brief Prepare to write LCD RAM. * @param [in] pstcLCD: LCD controller * @retval None */ void NT35510_PrepareWriteRAM(stc_lcd_controller_t *pstcLCD) { if (NULL != pstcLCD) { NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16WRamCmd); } } /** * @brief Set screen backlight. * @param [in] pstcLCD: LCD controller * @param [in] u8PWM: PWM level This parameter can be a value between Min_Data = 0 and Max_Data = 100 * @retval None */ void NT35510_SetBackLight(stc_lcd_controller_t *pstcLCD, uint8_t u8PWM) { float32_t f32PWM = ((float32_t)u8PWM * 2.55F); if (NULL != pstcLCD) { NT35510_WriteReg(pstcLCD, 0xBEU); NT35510_WriteData(pstcLCD, 0x05U); NT35510_WriteData(pstcLCD, (uint16_t)f32PWM); NT35510_WriteData(pstcLCD, 0x01U); NT35510_WriteData(pstcLCD, 0xFFU); NT35510_WriteData(pstcLCD, 0x00U); NT35510_WriteData(pstcLCD, 0x00U); } } /** * @brief Set Cursor position. * @param [in] pstcLCD: LCD controller * @param u16Xpos: Specifies the X position. * @param u16Ypos: Specifies the Y position. * @retval None */ void NT35510_SetCursor(stc_lcd_controller_t *pstcLCD, uint16_t u16Xpos, uint16_t u16Ypos) { if (NULL != pstcLCD) { if (0x1963U == m_stcLcdDevice.u16ID) { /* Convert X coordinate */ if (m_stcLcdDevice.u16Dir == 0U) { u16Xpos = m_stcLcdDevice.u16Width - 1U - u16Xpos; NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetXCmd); NT35510_WriteData(pstcLCD, 0U); NT35510_WriteData(pstcLCD, 0U); NT35510_WriteData(pstcLCD, u16Xpos >> 8); NT35510_WriteData(pstcLCD, u16Xpos & 0xFFU); } else { NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetXCmd); NT35510_WriteData(pstcLCD, u16Xpos >> 8); NT35510_WriteData(pstcLCD, u16Xpos & 0xFFU); NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Width - 1U) >> 8); NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Width - 1U) & 0xFFU); } NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetYCmd); NT35510_WriteData(pstcLCD, u16Ypos >> 8); NT35510_WriteData(pstcLCD, u16Ypos & 0xFFU); NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Height - 1U) >> 8); NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Height - 1U) & 0xFFU); } else if (0x5510U == m_stcLcdDevice.u16ID) { NT35510_WriteRegData(pstcLCD, m_stcLcdDevice.u16SetXCmd, (u16Xpos >> 8U)); NT35510_WriteRegData(pstcLCD, (m_stcLcdDevice.u16SetXCmd + 1U), (u16Xpos & 0xFFU)); NT35510_WriteRegData(pstcLCD, m_stcLcdDevice.u16SetYCmd, (u16Ypos >> 8U)); NT35510_WriteRegData(pstcLCD, (m_stcLcdDevice.u16SetYCmd + 1U), (u16Ypos & 0xFFU)); } else { /* NT35310 / 9341 / 5310 / 7789 etc */ NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetXCmd); NT35510_WriteData(pstcLCD, (u16Xpos >> 8)); NT35510_WriteData(pstcLCD, (u16Xpos & 0xFFU)); NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetYCmd); NT35510_WriteData(pstcLCD, (u16Ypos >> 8)); NT35510_WriteData(pstcLCD, (u16Ypos & 0xFFU)); } } } /** * @brief Write pixel. * @param [in] pstcLCD: LCD controller * @param u16Xpos: Specifies the X position. * @param u16Ypos: Specifies the Y position. * @param u16RGBCode: The RGB pixel color in RGB565 format * @retval None */ void NT35510_WritePixel(stc_lcd_controller_t *pstcLCD, uint16_t u16Xpos, uint16_t u16Ypos, uint16_t u16RGBCode) { if (NULL != pstcLCD) { /* Set cursor */ NT35510_SetCursor(pstcLCD, u16Xpos, u16Ypos); /* Prepare to write to LCD RAM */ NT35510_PrepareWriteRAM(pstcLCD); NT35510_WriteData(pstcLCD, u16RGBCode); } } /** * @brief Draw line. * @param [in] pstcLCD: LCD controller * @param u16X1: Specifies the X position 1. * @param u16X2: Specifies the X position 2. * @param u16Y1: Specifies the Y position 1. * @param u16Y2: Specifies the Y position 2. * @param u16RGBCode: The RGB pixel color in RGB565 format * @retval None */ void NT35510_DrawLine(stc_lcd_controller_t *pstcLCD, uint16_t u16X1, uint16_t u16Y1, uint16_t u16X2, uint16_t u16Y2, uint16_t u16RGBCode) { int16_t t; int16_t xerr = 0; int16_t yerr = 0; int16_t delta_x; int16_t delta_y; int16_t distance; int16_t incx; int16_t incy; int16_t Row; int16_t Col; if (NULL != pstcLCD) { Row = (int16_t)u16X1; Col = (int16_t)u16Y1; delta_x = ((int16_t)u16X2 - (int16_t)u16X1); /* calc delta X, Y*/ delta_y = ((int16_t)u16Y2 - (int16_t)u16Y1); if (delta_x > 0) { incx = 1; /* forward u8Direction */ } else if (delta_x == 0) { incx = 0; /* vertical line */ } else { incx = -1; /* reverse direction */ delta_x = -delta_x; } if (delta_y > 0) { incy = 1; /* downward direction */ } else if (delta_y == 0) { incy = 0; /* horizontal line */ } else { incy = -1; /* upward direction */ delta_y = -delta_y; } if (delta_x > delta_y) { distance = delta_x; /* set axis */ } else { distance = delta_y; } for (t = 0; t <= (distance + 1); t++) { NT35510_WritePixel(pstcLCD, (uint16_t)Row, (uint16_t)Col, u16RGBCode); /* draw pixel */ xerr += delta_x ; yerr += delta_y ; if (xerr > distance) { xerr -= distance; Row += incx; } if (yerr > distance) { yerr -= distance; Col += incy; } } } } /** * @brief Draw a circle. * @param [in] pstcLCD: LCD controller * @param [in] u16Xpos: X position * @param [in] u16Ypos: Y position * @param [in] u16Radius: Circle radius * @param u16RGBCode: The RGB pixel color in RGB565 format * @retval None */ void NT35510_DrawCircle(stc_lcd_controller_t *pstcLCD, uint16_t u16Xpos, uint16_t u16Ypos, uint16_t u16Radius, uint16_t u16RGBCode) { int32_t decision; /* Decision Variable */ uint32_t current_x; /* Current X Value */ uint32_t current_y; /* Current Y Value */ if (NULL != pstcLCD) { decision = 3 - ((int32_t)u16Radius * 2); current_x = 0U; current_y = u16Radius; while (current_x <= current_y) { NT35510_WritePixel(pstcLCD, (u16Xpos + (uint16_t)current_x), (u16Ypos - (uint16_t)current_y), u16RGBCode); NT35510_WritePixel(pstcLCD, (u16Xpos + (uint16_t)current_y), (u16Ypos - (uint16_t)current_x), u16RGBCode); NT35510_WritePixel(pstcLCD, (u16Xpos + (uint16_t)current_y), (u16Ypos + (uint16_t)current_x), u16RGBCode); NT35510_WritePixel(pstcLCD, (u16Xpos + (uint16_t)current_x), (u16Ypos + (uint16_t)current_y), u16RGBCode); NT35510_WritePixel(pstcLCD, (u16Xpos - (uint16_t)current_x), (u16Ypos + (uint16_t)current_y), u16RGBCode); NT35510_WritePixel(pstcLCD, (u16Xpos - (uint16_t)current_y), (u16Ypos + (uint16_t)current_x), u16RGBCode); NT35510_WritePixel(pstcLCD, (u16Xpos - (uint16_t)current_x), (u16Ypos - (uint16_t)current_y), u16RGBCode); NT35510_WritePixel(pstcLCD, (u16Xpos - (uint16_t)current_y), (u16Ypos - (uint16_t)current_x), u16RGBCode); current_x++; /* Bresenham algorithm */ if (decision < 0) { decision += ((4 * (int32_t)current_x) + 6); } else { decision += (10 + (4 * ((int32_t)current_x - (int32_t)current_y))); current_y--; } } } } /** * @brief Fill a triangle (between 3 points). * @param [in] pstcLCD: LCD controller * @param [in] u16X1: Point 1 X position * @param [in] u16Y1: Point 1 Y position * @param [in] u16X2: Point 2 X position * @param [in] u16Y2: Point 2 Y position * @param [in] u16X3: Point 3 X position * @param [in] u16Y3: Point 3 Y position * @param u16RGBCode: The RGB pixel color in RGB565 format * @retval None */ void NT35510_FillTriangle(stc_lcd_controller_t *pstcLCD, uint16_t u16X1, uint16_t u16Y1, uint16_t u16X2, uint16_t u16Y2, uint16_t u16X3, uint16_t u16Y3, uint16_t u16RGBCode) { uint16_t deltax; uint16_t deltay; int16_t xoff; int16_t yoff; int16_t xinc1; int16_t xinc2; int16_t yinc1; int16_t yinc2; uint16_t den; uint16_t num; uint16_t numadd; uint16_t numpixels; uint16_t curpixel; if (NULL != pstcLCD) { xoff = (int16_t)u16X1; /* Start x off at the first pixel */ yoff = (int16_t)u16Y1; /* Start y off at the first pixel */ /* The difference between the x's */ if (u16X2 > u16X1) { deltax = (u16X2 - u16X1); } else { deltax = (u16X1 - u16X2); } /* The difference between the y's */ if (u16Y2 > u16Y1) { deltay = (u16Y2 - u16Y1); } else { deltay = (u16Y1 - u16Y2); } if (u16X2 >= u16X1) { /* The x-values are increasing */ xinc1 = 1; xinc2 = 1; } else { /* The x-values are decreasing */ xinc1 = -1; xinc2 = -1; } if (u16Y2 >= u16Y1) { /* The y-values are increasing */ yinc1 = 1; yinc2 = 1; } else { /* The y-values are decreasing */ yinc1 = -1; yinc2 = -1; } /* There is at least one x-value for every y-value */ if (deltax >= deltay) { xinc1 = 0; /* Don't change the x when numerator >= denominator */ yinc2 = 0; /* Don't change the y for every iteration */ den = deltax; num = (deltax / 2U); numadd = deltay; numpixels = deltax; /* There are more x-values than y-values */ } else { /* There is at least one y-value for every x-value */ xinc2 = 0; /* Don't change the x for every iteration */ yinc1 = 0; /* Don't change the y when numerator >= denominator */ den = deltay; num = (deltay / 2U); numadd = deltax; numpixels = deltay; /* There are more y-values than x-values */ } for (curpixel = 0U; curpixel <= numpixels; curpixel++) { NT35510_DrawLine(pstcLCD, (uint16_t)xoff, (uint16_t)yoff, u16X3, u16Y3, u16RGBCode); num += numadd; /* Increase the numerator by the top of the fraction */ /* Check if numerator >= denominator */ if (num >= den) { num -= den; /* Calculate the new numerator value */ xoff += xinc1; /* Change the x as appropriate */ yoff += yinc1; /* Change the y as appropriate */ } xoff += xinc2; /* Change the x as appropriate */ yoff += yinc2; /* Change the y as appropriate */ } } } /** * @brief Draw rectangle. * @param [in] pstcLCD: LCD controller * @param [in] u16X1: Point 1 X position * @param [in] u16Y1: Point 1 Y position * @param [in] u16X2: Point 2 X position * @param [in] u16Y2: Point 2 Y position * @param u16RGBCode: The RGB pixel color in RGB565 format * @retval None */ void NT35510_DrawRectangle(stc_lcd_controller_t *pstcLCD, uint16_t u16X1, uint16_t u16Y1, uint16_t u16X2, uint16_t u16Y2, uint16_t u16RGBCode) { if (NULL != pstcLCD) { NT35510_DrawLine(pstcLCD, u16X1, u16Y1, u16X2, u16Y1, u16RGBCode); NT35510_DrawLine(pstcLCD, u16X1, u16Y1, u16X1, u16Y2, u16RGBCode); NT35510_DrawLine(pstcLCD, u16X1, u16Y2, u16X2, u16Y2, u16RGBCode); NT35510_DrawLine(pstcLCD, u16X2, u16Y1, u16X2, u16Y2, u16RGBCode); } } /** * @brief Clear screen. * @param [in] pstcLCD: LCD controller * @param u16RGBCode: The RGB pixel color in RGB565 format * @retval None */ void NT35510_Clear(stc_lcd_controller_t *pstcLCD, uint16_t u16RGBCode) { uint32_t i; uint32_t u32TotalPoint; if (NULL != pstcLCD) { /* Set cursor */ NT35510_SetCursor(pstcLCD, 0U, 0U); /* Prepare to write to LCD RAM */ NT35510_PrepareWriteRAM(pstcLCD); u32TotalPoint = (uint32_t)m_stcLcdDevice.u16Width * (uint32_t)m_stcLcdDevice.u16Height; for (i = 0UL; i < u32TotalPoint; i++) { NT35510_WriteData(pstcLCD, u16RGBCode); } } }   基于硬件I2C的触摸驱动实现: /** * @brief Read register on touch pad register. * @param [in] pstcGt9xxLL Pointer to a @ref stc_gt9xx_ll_t structure * @param [in] u16Reg Register to be read * @param [out] pu8RegValue The buffer for reading * @param [in] u32Len The buffer size for bytes * @retval None */ void GT9XX_REG_Read(const stc_gt9xx_ll_t *pstcGt9xxLL, uint16_t u16Reg, uint8_t *pu8RegValue, uint32_t u32Len) { uint8_t au8RegAddr[2]; if ((NULL != pstcGt9xxLL) && (NULL != pstcGt9xxLL->Read) && (NULL != pu8RegValue)) { au8RegAddr[0] = (uint8_t)((u16Reg & 0xFF00U) >> 8); au8RegAddr[1] = (uint8_t)(u16Reg & 0x00FFU); (void)pstcGt9xxLL->Read(au8RegAddr, ARRAY_SZ(au8RegAddr), pu8RegValue, u32Len); } } /** * @brief Write register on touch pad register. * @param [in] pstcGt9xxLL Pointer to a @ref stc_gt9xx_ll_t structure * @param [in] u16Reg Register to be write * @param [in] pu8RegValue The buffer for writing * @param [in] u32Len The buffer size for bytes * @retval None */ void GT9XX_REG_Write(const stc_gt9xx_ll_t *pstcGt9xxLL, uint16_t u16Reg, const uint8_t *pu8RegValue, uint32_t u32Len) { uint8_t au8RegAddr[2]; if ((NULL != pstcGt9xxLL) && (NULL != pstcGt9xxLL->Write) && (NULL != pu8RegValue)) { au8RegAddr[0] = (uint8_t)((u16Reg & 0xFF00U) >> 8); au8RegAddr[1] = (uint8_t)(u16Reg & 0x00FFU); (void)pstcGt9xxLL->Write(au8RegAddr, ARRAY_SZ(au8RegAddr), pu8RegValue, u32Len); } } /** * @brief Reset GT9XX. * @param [in] pstcGt9xxLL Pointer to a @ref stc_gt9xx_ll_t structure. * @retval None */ void GT9XX_SoftReset(const stc_gt9xx_ll_t *pstcGt9xxLL) { uint8_t u8RegValue = 0x02U; GT9XX_REG_Write(pstcGt9xxLL, GT9XX_COMMAND, &u8RegValue, 1UL); } /** * @brief Read GT9XX touch status. * @param [in] pstcGt9xxLL Pointer to a @ref stc_gt9xx_ll_t structure. * @retval Touch status */ uint8_t GT9XX_ReadTouchStatus(const stc_gt9xx_ll_t *pstcGt9xxLL) { uint8_t u8Status = 0U; GT9XX_REG_Read(pstcGt9xxLL, GT9XX_TOUCH_STATUS, &u8Status, 1UL); return u8Status; } /** * @brief Read GT9XX ID. * @param [in] pstcGt9xxLL Pointer to a @ref stc_gt9xx_ll_t structure. * @param [out] pu8IDValue The buffer for reading ID * @param [in] u32Len The buffer size for bytes * @retval None */ void GT9XX_ReadProductID(const stc_gt9xx_ll_t *pstcGt9xxLL, uint8_t *pu8IDValue, uint32_t u32Len) { GT9XX_REG_Read(pstcGt9xxLL, GT9XX_PRODUCT_ID, pu8IDValue, u32Len); } /** * @brief Read GT9XX point. * @param [in] pstcGt9xxLL Pointer to a @ref stc_gt9xx_ll_t structure. * @param [in] u16Point Touch pad point * @param [out] pu16X Point x coordinate * @param [out] pu16Y Point y coordinate * @retval None */ void GT9XX_GetXY(const stc_gt9xx_ll_t *pstcGt9xxLL, uint16_t u16Point, uint16_t *pu16X, uint16_t *pu16Y) { uint8_t au8Tmp[4]; if ((pu16X != NULL) && (pu16Y != NULL)) { GT9XX_REG_Read(pstcGt9xxLL, u16Point, au8Tmp, 4UL); (*pu16X) = (uint16_t)au8Tmp[0] | ((uint16_t)au8Tmp[1] << 8); (*pu16Y) = (uint16_t)au8Tmp[2] | ((uint16_t)au8Tmp[3] << 8); } }   主程序: /** * @brief BSP clock initialize. * SET board system clock to PLLH@160MHz * Flash: 3 wait * SRAM_H: 0 wait * SRAM_B: 1 wait * PCLK0: 160MHz * PCLK1: 80MHz * PCLK2: 40MHz * PCLK3: 40MHz * PCLK4: 80MHz * EXCLK: 40MHz * HCLK: 160MHz * @param None * @retval None */ void BSP_CLK_Init(void) { stc_clock_xtal_init_t stcXtalInit; stc_clock_pll_init_t stcPLLHInit; /* PCLK0, HCLK Max 200MHz */ /* PCLK1, PCLK4 Max 100MHz */ /* PCLK2, EXCLK Max 60MHz */ /* PCLK3 Max 50MHz */ CLK_SetClockDiv(CLK_BUS_CLK_ALL, (CLK_PCLK0_DIV1 | CLK_PCLK1_DIV2 | CLK_PCLK2_DIV4 | CLK_PCLK3_DIV4 | CLK_PCLK4_DIV2 | CLK_EXCLK_DIV4 | CLK_HCLK_DIV1)); GPIO_AnalogCmd(BSP_XTAL_PORT, BSP_XTAL_IN_PIN | BSP_XTAL_OUT_PIN, ENABLE); (void)CLK_XtalStructInit(&stcXtalInit); /* Config Xtal and enable Xtal */ stcXtalInit.u8Mode = CLK_XTAL_MD_OSC; stcXtalInit.u8Drv = CLK_XTAL_DRV_ULOW; stcXtalInit.u8State = CLK_XTAL_ON; stcXtalInit.u8StableTime = CLK_XTAL_STB_2MS; (void)CLK_XtalInit(&stcXtalInit); (void)CLK_PLLStructInit(&stcPLLHInit); /* VCO = (8/1)*800 = 640MHz*/ stcPLLHInit.u8PLLState = CLK_PLL_ON; stcPLLHInit.PLLCFGR = 0UL; stcPLLHInit.PLLCFGR_f.PLLM = 1UL - 1UL; stcPLLHInit.PLLCFGR_f.PLLN = 80UL - 1UL; stcPLLHInit.PLLCFGR_f.PLLP = 4UL - 1UL; stcPLLHInit.PLLCFGR_f.PLLQ = 4UL - 1UL; stcPLLHInit.PLLCFGR_f.PLLR = 4UL - 1UL; stcPLLHInit.PLLCFGR_f.PLLSRC = CLK_PLL_SRC_XTAL; (void)CLK_PLLInit(&stcPLLHInit); /* 3 cycles for 150 ~ 200MHz */ (void)EFM_SetWaitCycle(EFM_WAIT_CYCLE3); /* 3 cycles for 150 ~ 200MHz */ GPIO_SetReadWaitCycle(GPIO_RD_WAIT3); CLK_SetSysClockSrc(CLK_SYSCLK_SRC_PLL); } /** * @brief Return true is the touchpad is pressed * @param None * @retval Press state */ static bool TOUCHPAD_IsPressed(void) { uint8_t u8Tmp; uint8_t u8Status; bool bPressed = false; BSP_GT9XX_REG_Read(GT9XX_TOUCH_STATUS, &u8Status, 1UL); if ((u8Status & 0x80U) != 0U) { u8Tmp = 0U; BSP_GT9XX_REG_Write(GT9XX_TOUCH_STATUS, &u8Tmp, 1U); if ((0U < (u8Status & 0x0FU)) && ((u8Status & 0x0FU) < 6U)) { bPressed = true; } } return bPressed; } /** * @brief Get touch data. * @param [out] pstcData Pointer to a @ref stc_touchpad_data_t structure. * @retval None */ static void TOUCHPAD_Read(stc_touchpad_data_t *pstcData) { static uint16_t u16LastX = 0U; static uint16_t u16LastY = 0U; /*Save the pressed coordinates and the state*/ if (TOUCHPAD_IsPressed()) { BSP_GT9XX_GetXY(GT9XX_POINT1, &u16LastX, &u16LastY); pstcData->enPointPress = SET; } else { pstcData->enPointPress = RESET; } /*Set the last pressed coordinates*/ pstcData->stcPoint.u16X = u16LastX; pstcData->stcPoint.u16Y = u16LastY; } /** * @brief Check if a point is on an window * @param [in] pstcWin Pointer to a @ref stc_touchpad_window_t structure. * @param [in] pstcPoint Pointer to a @ref stc_touchpad_point_t structure. * @retval bool: * - true: The point is in the area. * - false: The point is out the area. */ bool TOUCHPAD_IsPointOn(const stc_touchpad_window_t *pstcWin, const stc_touchpad_point_t *pstcPoint) { bool bIsPointOnWin = false; if ((pstcPoint->u16X >= pstcWin->u16X1 && pstcPoint->u16X <= pstcWin->u16X2) && \ (pstcPoint->u16Y >= pstcWin->u16Y1 && pstcPoint->u16Y <= pstcWin->u16Y2)) { bIsPointOnWin = true; } return bIsPointOnWin; } /** * @brief Main function of LCD project * @param None * @retval int32_t return value, if needed */ int32_t main(void) { uint8_t i; uint16_t u16Width; uint16_t u16Height; bool bIsPointOnWin; const uint8_t u8RectangleCount = 3U; uint16_t u16WinSize; stc_touchpad_window_t stcWin; /* MCU Peripheral registers write unprotected */ LL_PERIPH_WE(LL_PERIPH_GPIO | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_EFM); /* Initialize system clock: */ BSP_CLK_Init(); BSP_IO_Init(); BSP_LCD_IO_Init(); /* Initialize LCD touch pad */ BSP_GT9XX_Init(); /* HW Reset LCD */ BSP_LCD_RSTCmd(EIO_PIN_RESET); /* RST# to low */ DDL_DelayMS(50UL); BSP_LCD_RSTCmd(EIO_PIN_SET); /* RST# to high */ DDL_DelayMS(50UL); /* Initialize NT35510 LCD */ BSP_NT35510_Init(); /* Clear LCD screen */ BSP_NT35510_Clear(LCD_COLOR_BLACK); /* Turn on LCD backlight */ BSP_LCD_BKLCmd(EIO_PIN_SET); /* Set LCD cursor */ BSP_NT35510_SetCursor(0U, 0U); /* MCU Peripheral registers write protected */ LL_PERIPH_WP(LL_PERIPH_GPIO | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_EFM); u16Width = BSP_NT35510_GetPixelWidth(); u16Height = BSP_NT35510_GetPixelHeight(); for (;;) { for (i = 0U; i < u8RectangleCount; i++) { bIsPointOnWin = false; u16WinSize = u16Width / u8RectangleCount; stcWin.u16X1 = (i * u16WinSize); stcWin.u16Y1 = (u16Height / 2U) - (u16WinSize / 2U); stcWin.u16X2 = stcWin.u16X1 + u16WinSize - 1U; stcWin.u16Y2 = (u16Height / 2U) + (u16WinSize / 2U) - 1U; BSP_NT35510_DrawRectangle(stcWin.u16X1, stcWin.u16Y1, stcWin.u16X2, stcWin.u16Y2, LCD_COLOR_GREEN); do { (void)memset(&m_stcTouchData, 0, sizeof(m_stcTouchData)); TOUCHPAD_Read(&m_stcTouchData); if (m_stcTouchData.enPointPress == SET) { bIsPointOnWin = TOUCHPAD_IsPointOn(&stcWin, &m_stcTouchData.stcPoint); } } while (false == bIsPointOnWin); BSP_NT35510_Clear(LCD_COLOR_BLACK); } BSP_NT35510_DrawCircle(u16Width / 2U, u16Height / 2U, u16Width / 4U, LCD_COLOR_RED); DDL_DelayMS(1000UL); BSP_NT35510_Clear(LCD_COLOR_RED); DDL_DelayMS(1000UL); BSP_NT35510_Clear(LCD_COLOR_GREEN); DDL_DelayMS(1000UL); BSP_NT35510_Clear(LCD_COLOR_BLUE); DDL_DelayMS(1000UL); /* Clear LCD screen */ BSP_NT35510_Clear(LCD_COLOR_BLACK); } }   6.运行效果 注意事项:拨码开关SW2选择EXMC功能 & 码开关SW4选择LCD功! [localvideo]865b7898a142bdd8191184d2e77f3d5f[/localvideo]  

  • 2024-02-19
  • 发表了主题帖: 【国民技术车规MCU N32A455开发板】02.熟悉CAN通讯(邮箱、ID过滤等),与PC通讯测试

    本帖最后由 xld0932 于 2024-2-19 11:32 编辑 1.概述 当前CAN通讯应用越来越广泛、汽车电子、工业控制,到近些年的电动车,都开始使用CAN组网通讯了,这都得益于CAN的高效、稳定和规范。国民技术N32A455系列MCU带有2组CAN通讯接口,最高波特率可达到1Mbit/s,支持CAN协议2.0A和2.0B,支持时间触发通讯功能;每个CAN都有两个3级深度的接收FIFO、共有14个过滤器组、3个发送邮箱,通过接收FIFO和过滤机制,降低了CAN消息的实时响应要求,减少MCU不必要的消耗,同时也提升了MCU的利用率。   2.熟悉CAN模块 2.1.工作模式 初始化、正常和睡眠模式是CAN的三种主要工作模式。软件只有在CAN处于初始化模式时才能进行初始化配置、在初始化完成后,软件配置CAN进入正常模式、通过配置寄存器相应位可以使CAN进入睡眠模式,在进入睡眠模式后,可以通过硬件自动唤醒(检测到CAN总线的活动),也可以通过软件唤醒(操作寄存器位),需要注意的是在进入正常模式之前,CAN必须与CAN总线同步。另外还有测试模式(回环模式、静默模式、回环静默模式)、调试模式。 2.2.发送邮箱 应用程序可以通过三个发送邮箱发送消息,发送三个邮箱消息的顺序是由发送调度器根据消息的优先级决定的,优先级可以由消息的标识符决定,也可以由发送请求的顺序决定。 2.3.接收过滤器 每个 CAN 有 14 个可配置的标识符过滤器组。应用配置标识符过滤器组后,接收邮箱会自动接收需要的邮件,丢弃其他邮件。 2.4.接收FIFO 每个 CAN 有两个接收 FIFO,每个 FIFO 可以存储三个完整的报文。无需应用程序管理,由硬件管理。   3.CAN通讯示例 3.1.GPIO初始化配置 /* PD8_CAN1_RX */ #define CAN1_RX_RCC RCC_APB2_PERIPH_GPIOD #define CAN1_RX_GPIO GPIOD #define CAN1_RX_PIN GPIO_PIN_8 /* PD9_CAN1_TX */ #define CAN1_TX_RCC RCC_APB2_PERIPH_GPIOD #define CAN1_TX_GPIO GPIOD #define CAN1_TX_PIN GPIO_PIN_9 /* PE0_CAN1_STB */ #define CAN1_STB_RCC RCC_APB2_PERIPH_GPIOE #define CAN1_STB_GPIO GPIOE #define CAN1_STB_PIN GPIO_PIN_0 void CAN_Configuration(void) { GPIO_InitType GPIO_InitStructure; RCC_EnableAPB2PeriphClk(CAN1_RX_RCC | RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = CAN1_RX_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitPeripheral(CAN1_RX_GPIO, &GPIO_InitStructure); RCC_EnableAPB2PeriphClk(CAN1_TX_RCC | RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = CAN1_TX_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitPeripheral(CAN1_TX_GPIO, &GPIO_InitStructure); RCC_EnableAPB2PeriphClk(CAN1_STB_RCC, ENABLE); GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = CAN1_STB_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitPeripheral(CAN1_STB_GPIO, &GPIO_InitStructure); GPIO_WriteBit(CAN1_STB_GPIO, CAN1_STB_PIN, Bit_RESET); GPIO_ConfigPinRemap(GPIO_RMP1_CAN1, ENABLE); ...... } 3.2.CAN通讯参数配置 void CAN_Configuration(void) { ...... CAN_InitType CAN_InitStructure; RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_CAN1, ENABLE); CAN_DeInit(CAN1); CAN_InitStruct(&CAN_InitStructure); CAN_InitStructure.TTCM = DISABLE; CAN_InitStructure.ABOM = DISABLE; CAN_InitStructure.AWKUM = DISABLE; CAN_InitStructure.NART = DISABLE; CAN_InitStructure.RFLM = DISABLE; CAN_InitStructure.TXFP = ENABLE; CAN_InitStructure.OperatingMode = CAN_Normal_Mode; CAN_InitStructure.RSJW = CAN_RSJW_1tq; CAN_InitStructure.TBS1 = CAN_TBS1_14tq; CAN_InitStructure.TBS2 = CAN_TBS2_3tq; CAN_InitStructure.BaudRatePrescaler = 4; CAN_Init(CAN1, &CAN_InitStructure); ...... } 3.3.CAN过滤器配置 #define CAN_FILTER_STDID(STDID) ((STDID & 0x7FF) << 5) #define CAN_FILTER_EXTID_H(EXTID) ((uint16_t)(((EXTID <<3) | 0x04) >> 16)) #define CAN_FILTER_EXTID_L(EXTID) ((uint16_t)(( EXTID <<3) | 0x04)) #define CAN_STD_ID_H_MASK_CARE (0xFFE0) #define CAN_STD_ID_L_MASK_CARE (0x0000) #define CAN_STD_ID_H_MASK_DONT_CARE (0x0000) #define CAN_STD_ID_L_MASK_DONT_CARE (0x0000) #define CAN_EXT_ID_H_MASK_CARE (0xFFFF) #define CAN_EXT_ID_L_MASK_CARE (0xFFF8) #define CAN_EXT_ID_H_MASK_DONT_CARE (0x0000) #define CAN_EXT_ID_L_MASK_DONT_CARE (0x0000) void CAN_Configuration(void) { ...... CAN_FilterInitType CAN_FilterInitStructure; CAN_FilterInitStructure.Filter_Num = 0; CAN_FilterInitStructure.Filter_Mode = CAN_Filter_IdMaskMode; CAN_FilterInitStructure.Filter_Scale = CAN_Filter_32bitScale; CAN_FilterInitStructure.Filter_HighId = CAN_FILTER_STDID(0x400); CAN_FilterInitStructure.Filter_LowId = CAN_FILTER_STDID(0x400); CAN_FilterInitStructure.FilterMask_HighId = CAN_STD_ID_H_MASK_DONT_CARE; CAN_FilterInitStructure.FilterMask_LowId = CAN_STD_ID_H_MASK_DONT_CARE; CAN_FilterInitStructure.Filter_FIFOAssignment = CAN_FIFO0; CAN_FilterInitStructure.Filter_Act = ENABLE; CAN1_InitFilter(&CAN_FilterInitStructure); CAN_INTConfig(CAN1, CAN_INT_FMP0, ENABLE); ...... } 3.4.CAN中断配置及处理 CanRxMessage CAN_RxMessage[10]; uint8_t CAN_RxMessage_WriteCursor = 0; uint8_t CAN_RxMessage_ReadCursor = 0; void CAN_Configuration(void) { ...... NVIC_InitType NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void CAN1_RX0_IRQHandler(void) { CAN_ReceiveMessage(CAN1, CAN_FIFO0, &CAN_RxMessage[CAN_RxMessage_WriteCursor++]); if (CAN_RxMessage_WriteCursor > 10) { CAN_RxMessage_WriteCursor = 0; } } 3.5.接收发送处理 void CAN_RxMessageHandler(void) { uint8_t i = 0; if (CAN_RxMessage_ReadCursor != CAN_RxMessage_WriteCursor) { printf("\r\n"); if (CAN_RxMessage[CAN_RxMessage_ReadCursor].IDE == CAN_Extended_Id) { printf("\r\nReceive Frame[0x%X, %d]:", CAN_RxMessage[CAN_RxMessage_ReadCursor].ExtId, CAN_RxMessage[CAN_RxMessage_ReadCursor].DLC); } else { printf("\r\nReceive Frame[0x%X, %d]:", CAN_RxMessage[CAN_RxMessage_ReadCursor].StdId, CAN_RxMessage[CAN_RxMessage_ReadCursor].DLC); } for (i = 0; i < CAN_RxMessage[CAN_RxMessage_ReadCursor].DLC; i++) { printf(" 0x%02X", CAN_RxMessage[CAN_RxMessage_ReadCursor].Data[i]); } CAN_RxMessage_ReadCursor++; if (CAN_RxMessage_ReadCursor > 10) { CAN_RxMessage_ReadCursor = 0; } printf("\r\n"); } } void CAN_TxStdMessage(void) { CanTxMessage CAN_TxMessage; uint8_t TxMailbox = 0; uint8_t i = 0; CAN_TxMessage.StdId = 0x0400; CAN_TxMessage.IDE = CAN_ID_STD; CAN_TxMessage.RTR = CAN_RTRQ_DATA; CAN_TxMessage.DLC = 8; for (i = 0; i < CAN_TxMessage.DLC; i++) { CAN_TxMessage.Data[i] = i; } TxMailbox = CAN_TransmitMessage(CAN1, &CAN_TxMessage); if (TxMailbox != CAN_TxSTS_NoMailBox) { while (CAN_TransmitSTS(CAN1, TxMailbox) != CANTXSTSOK) { __ASM("nop"); } } else { printf("\r\n%s CAN_TxSTS_NoMailBox!!!", __FUNCTION__); } } void CAN_TxExtMessage(void) { CanTxMessage CAN_TxMessage; uint8_t TxMailbox = 0; uint8_t i = 0; CAN_TxMessage.ExtId = 0x12345678; CAN_TxMessage.IDE = CAN_ID_EXT; CAN_TxMessage.RTR = CAN_RTRQ_DATA; CAN_TxMessage.DLC = 8; for (i = 0; i < CAN_TxMessage.DLC; i++) { CAN_TxMessage.Data[i] = i; } TxMailbox = CAN_TransmitMessage(CAN1, &CAN_TxMessage); if (TxMailbox != CAN_TxSTS_NoMailBox) { while (CAN_TransmitSTS(CAN1, TxMailbox) != CANTXSTSOK) { __ASM("nop"); } } else { printf("\r\n%s CAN_TxSTS_NoMailBox!!!", __FUNCTION__); } }   4.测试结果 4.1.PC端使用PCAN工具收发数据 4.2.MCU在接收到CAN数据后,通过串口打印输出 4.3.硬件连接 需要注意的是我们使用的是CAN1,需要将J10这两个跳帽给短接上!!!   5.附件程序

  • 2024-02-07
  • 发表了主题帖: 【国民技术车规MCU N32A455开发板】01、搭建开发环境、创建基础工程

    1.开箱 春节前夕,收到了板载国民技术车规MCU的N32A455开发板!一块开发板、一根MiniUSB数据线……   2.准备工作 2.1.下载开发资料: 通过ftp://download.nationstech.com下载开发板相关资料:ftp://download.nationstech.com/2-Automotive-Grade MCU/下的N32A455xx_V1.2.0.zip 通过https://www.nationstech.com/zlxz455/官网去下载相应资料, 通过测评活动链接,下载官方提供的资料 额……还是建议到FTP服务器去下载,更新比较及时,官网上当前能下载到版本为1.1版本,FTP服务器最新版本为1.2 2.2.安装KEIL集成开发环境芯片支持包 在N32A455xx_V1.2.0\6-Software Development Kit目录下,双击Nationstech.N32A455_DFP.1.0.0.pack进行安装:   3.熟悉板载功能 我们这次测评的开发板型号为N32A455VEL7-EVB,所以对应的是N32A455xx_V1.2.0\5-Hardware Evaulation Board\N32A455VEL7-EVB_V1.1目录下的N32A455VEL7-EVB_V1.1.pdf原理图,通过N32A455VEL7-EVB开发板硬件使用指南,获知开发板功能如下: 开发板供电方式:通过DC插口供12V电源、通过MiniUSB接口供5V电源 板载NSLINK程序下载调试工具,支持JTAG和SWD两种连接方式,同时还带有一路虚拟串口 支持2路CAN和2路LIN 支持TF卡,SDIO接口 板载VS1053B音频电路 板载EEPROM 板载SPI FLASH和QSPI FLASH 板载5个机械按键,1个复位按键、1个唤醒按键、3个功能按键 板载三色LED灯、ADC功能的可调电阻 芯片的所有引脚都通过排针全部引出   4.基础工程 官方的示例程序存放在N32A455xx_V1.2.0\6-Software Development Kit\Nationstech.N32A455_Library.1.1.0目录下,firmware文件夹中存放的是驱动库程序,projects\n32a455_EVAL文件夹下存放的是基于开发板的示例程序。我们参考examples\GPIO\LedBlink示例程序、examples\GPIO\LedBlink示例程序、examples\USART\Printf示例程序,来创建一个新的基础工程。 4.1.创建工程:工程名->选择芯片型号->OK   4.2.添加工程源码:启动程序、CMSIS、驱动库、用户程序   4.3.配置工程   4.4.编写程序 #ifndef __MAIN_H__ #define __MAIN_H__ #ifdef __cplusplus extern "C" { #endif #include <stdint.h> #include <stdio.h> #include "n32a455.h" /* PA11_RLED */ #define RLED_RCC RCC_APB2_PERIPH_GPIOA #define RLED_GPIO GPIOA #define RLED_PIN GPIO_PIN_11 /* PB10_BLED */ #define BLED_RCC RCC_APB2_PERIPH_GPIOB #define BLED_GPIO GPIOB #define BLED_PIN GPIO_PIN_10 /* PA12_GLED */ #define GLED_RCC RCC_APB2_PERIPH_GPIOA #define GLED_GPIO GPIOA #define GLED_PIN GPIO_PIN_12 /* PD12_KEY */ #define S3_RCC RCC_APB2_PERIPH_GPIOD #define S3_GPIO GPIOD #define S3_PIN GPIO_PIN_12 /* PC6_KEY */ #define S4_RCC RCC_APB2_PERIPH_GPIOC #define S4_GPIO GPIOC #define S4_PIN GPIO_PIN_6 /* PC7_KEY */ #define S5_RCC RCC_APB2_PERIPH_GPIOC #define S5_GPIO GPIOC #define S5_PIN GPIO_PIN_7 #ifdef __cplusplus } #endif #endif   #include "main.h" void LED_Init(void) { GPIO_InitType GPIO_InitStructure; RCC_EnableAPB2PeriphClk(RLED_RCC, ENABLE); GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = RLED_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitPeripheral(RLED_GPIO, &GPIO_InitStructure); GPIO_WriteBit(RLED_GPIO, RLED_PIN, Bit_SET); RCC_EnableAPB2PeriphClk(BLED_RCC, ENABLE); GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = BLED_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitPeripheral(BLED_GPIO, &GPIO_InitStructure); GPIO_WriteBit(BLED_GPIO, BLED_PIN, Bit_SET); RCC_EnableAPB2PeriphClk(GLED_RCC, ENABLE); GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = GLED_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitPeripheral(GLED_GPIO, &GPIO_InitStructure); GPIO_WriteBit(GLED_GPIO, GLED_PIN, Bit_SET); } void LED_ON(GPIO_Module *GPIOn, uint16_t PINn) { GPIO_WriteBit(GPIOn, PINn, Bit_RESET); } void LED_OFF(GPIO_Module *GPIOn, uint16_t PINn) { GPIO_WriteBit(GPIOn, PINn, Bit_SET); } void LED_Toggle(GPIO_Module *GPIOn, uint16_t PINn) { if (GPIO_ReadOutputDataBit(GPIOn, PINn) == Bit_RESET) { GPIO_WriteBit(GPIOn, PINn, Bit_SET); } else { GPIO_WriteBit(GPIOn, PINn, Bit_RESET); } } void KEY_Init(void) { GPIO_InitType GPIO_InitStructure; RCC_EnableAPB2PeriphClk(S3_RCC, ENABLE); GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = S3_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitPeripheral(S3_GPIO, &GPIO_InitStructure); RCC_EnableAPB2PeriphClk(S4_RCC, ENABLE); GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = S4_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitPeripheral(S4_GPIO, &GPIO_InitStructure); RCC_EnableAPB2PeriphClk(S5_RCC, ENABLE); GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = S5_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitPeripheral(S5_GPIO, &GPIO_InitStructure); } void USART_Configuration(void) { GPIO_InitType GPIO_InitStructure; USART_InitType USART_InitStructure; RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = GPIO_PIN_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1, ENABLE); USART_StructInit(&USART_InitStructure); USART_InitStructure.BaudRate = 115200; USART_InitStructure.WordLength = USART_WL_8B; USART_InitStructure.StopBits = USART_STPB_1; USART_InitStructure.Parity = USART_PE_NO; USART_InitStructure.Mode = USART_MODE_TX; USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE; USART_Init(USART1, &USART_InitStructure); USART_Enable(USART1, ENABLE); } int main(void) { LED_Init(); KEY_Init(); USART_Configuration(); printf("\r\nN32A455VEL7-EVB V1.1 %s %s", __DATE__, __TIME__); while (1) { GPIO_WriteBit(RLED_GPIO, RLED_PIN, GPIO_ReadInputDataBit(S3_GPIO, S3_PIN)); GPIO_WriteBit(BLED_GPIO, BLED_PIN, GPIO_ReadInputDataBit(S4_GPIO, S4_PIN)); GPIO_WriteBit(GLED_GPIO, GLED_PIN, GPIO_ReadInputDataBit(S5_GPIO, S5_PIN)); } } int fputc(int ch, FILE* f) { USART_SendData(USART1, (uint8_t)ch); while (USART_GetFlagStatus(USART1, USART_FLAG_TXDE) == RESET); return (ch); }   5.编译、运行 5.1.打印输出   5.2.运行视频 [localvideo]ed26d6103ac4f6c11bdcac0a0478b139[/localvideo]   6.附件

  • 2024-02-05
  • 回复了主题帖: 【小华工控新品HC32F448】06.WDT/SWDT看门狗计数器给程序的正常运行保驾护航

    Jacktang 发表于 2024-2-5 07:48 看门狗计数器用的很好啊,学习学习

  • 回复了主题帖: 【小华工控新品HC32F448】07.使用XHCode基于HC32F448创建闪烁LED基础工程

    Jacktang 发表于 2024-2-5 07:46 可以把这个贴当做用XHCode创建一个闪烁LED的基础工程的教程啦

  • 2024-02-04
  • 发表了主题帖: 【小华工控新品HC32F448】07.使用XHCode基于HC32F448创建闪烁LED基础工程

    本帖最后由 xld0932 于 2024-2-4 14:27 编辑 1.概述 XHCode是小华半导体推出的一款协助用户配置生成XHSC MCU基础代码的软件工具,它包含了管脚和模块配置、时钟配置和工程配置3部分,今天来基于HC32F448系列MCU,使用XHCode创建一个闪烁LED的基础工程,来记录一下使用体验。   2.安装XHCode 从小华半导体官网上可以下载最新版本的XHCode工具,双击安装文件,根据提示进行安装,这个安装过程比较简单,如下所示:   3.创建闪烁LED工程 3.1.双击XHSC XHCode软件,在左上角型号的下拉菜单中选择HC32F448MCTI-LQFP80,如下所示:   3.2.管脚和模块配置界面:在左侧MCU引脚配置图中先配置一些基础配置,比如PA13\PA14配置为程序调试/烧录引脚、配置PC14/PC15为外部32.768晶振的输入端口、配置PH0/PH1为外部主晶振的输入端口;然后根据EV_F448_LQ80_Rev1.0开发板的原理图,将PA2配置为GPIO-Output输出模式,如下所示: 在配置GPIO时,发现现在还有少部分的外设无法配置,可能需要后面更新版本后才能配置吧;但对于GPIO来说,没有重命名Lable的功能,觉得有些不方便,将PA2添加一个LED的Lable,会显示更直观,更清楚不是么……   3.3.时钟配置界面:当选择HC32F448MCTI-LQFP80这颗芯片型号后,系统的时钟和总线频率配置大部分都是依据最大上限来配置的,个别没有达到上限的也是因为计算分频倍数的关系,同时满足不了多端的要求,就优先满足一边了,如下图所示: 在看这个时钟配置时,默认PLLSRC就是选用的XTAL,当在配置管脚和模块配置界面还没有配置时钟引脚时,这边就是这样的默认选择了,感觉管脚和模块配置界面与时钟配置界面的功能并没有联动起来,感觉有点功能欠缺的意思;另外就是在时钟配置界面上,对于频率的显示单位也没有统一起来,一部分单位是MHz,一部分的单位却是KHz,看上去有些杂乱。   3.4.工程配置界面:我们在工程名称中输入相应的工程名,选择工程IDE类型为MDK(这个工具支持KEIL MKD、IAR EWARM、Eclipse三个集成开发环境的工程生成),指定工程保存的位置以及驱动库(DDL)位置,先点击右上角的保存配置保存当前的工程,然后再点击右上角的生成代码,依据我们的工程配置生成相应的代码,如下所示: 需要注意的是,驱动库(DLL)位置不是指DLL下载存放的位置,当前这款工具还没有根据芯片型号自动下载对应驱动库程序的功能,而是需要我们提前下载好DLL驱动库,然后这边指定位置就是我们存放下载的DLL驱动库的位置:   3.5.生成的代码:我们发现生成的代码目录如下所示,有main和MDK两个文件夹,后面我才确认这边的main文件夹是多余的,因为MDK工程中的源程序,都是存放在MDK目录中的,所以这边需要原厂制作工具的再确认下:   4.编译工程 4.1.打开MDK目录下的LED.uvprojx工程文件,如下所示:   4.2.我们先想看一工程的配置,点击工具栏的配置按钮,在弹出配置窗口的Debug选项卡中确认使用的调试下载工具,然后再通过Utilities选项卡确认下载选项,如下所示: 我们需要将Reset and Run勾选上,这样我们在程序下载完成后,芯片就可以自动复位并运行了。   4.3.我们点击工具栏的工程编译按钮,编译结果发现有2处Error,对于官方示例程序,发现没有配置这2条语句的选项,所以就先屏蔽掉了,结果编译就顺利通过了: 自动生成的代码会产生编译错误实属不应该哈,大多数使用自动生成工具的来说,就是想快速的生产工程,对底层配置不想深究太多,出错后就不得不多花时间去检查了……   5.应用程序 在编译无误的工程上,我们就可以添加自己的应用程序了,因为闪烁LED的功能比较简单,我们就直接在main函数的for循环里添加了,每间隔500ms,LED显示状态翻转一次: /** * @brief Main function of the project * @param None * @retval int32_t return value, if needed */ int32_t main(void) { /* Register write unprotected for some required peripherals. */ LL_PERIPH_WE(LL_PERIPH_ALL); //Clock Config App_ClkCfg(); //Port Config App_PortCfg(); /* Register write protected for some required peripherals. */ LL_PERIPH_WP(LL_PERIPH_ALL); for (;;) { GPIO_TogglePins(GPIO_PORT_A, GPIO_PIN_02); DDL_DelayMS(500); } } 最后编译无误,下载运行OK哦!   6.总结 XHCode是一款用来便于开发的软件,理应做到配置功能齐全、生成代码无误,要做到这一点,XHCode还有很多工作需要去做,去测试、去完善、去适配;希望这款工具越做越好,尽早的可以给开发工程师带来便利!

  • 回复了主题帖: 测评入围名单: 国民技术车规MCU N32A455开发板

    个人信息无误,确认可以完成评测计划。

  • 回复了主题帖: 【小华工控新品HC32F448】01.搭建开发环境、创建基础工程

    Maker_kun 发表于 2024-1-22 19:41 开发板外设挺丰富的 嗯,除了板载资源,芯片所有的引脚也都扩展出来了,方便接一些其它的外设做测试验证

最近访客

< 1/6 >

统计信息

已有490人来访过

  • 芯积分:613
  • 好友:--
  • 主题:83
  • 回复:122

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言