xld0932

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

  • 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 开发板外设挺丰富的 嗯,除了板载资源,芯片所有的引脚也都扩展出来了,方便接一些其它的外设做测试验证

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

    1.概述 在产品设计中,我们经常会使用到看门狗功能,通过程序中设计的定时时间,周期的进行喂狗操作,从而保证程序运行在正常设计的程序流程,在程序运行有偏差的时候可以及时的纠正,防止异常的发生! 小华HC32F488系列MCU带有两个看门狗计数器,一种是计数时钟源为专用内部 RC(SWDTLRC: 10KHz)的专用看门狗计数器(SWDT),另一种是计数时钟源为 PCLK3 的通用看门狗计数器(WDT)。专用看门狗和通用看门狗是 16 位递减计数器,用来监测由于外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行而产生的软件故障。   2.共同点和不同点 都支持窗口功能:在计数开始前可预设窗口区间,计数值位于窗口区间时,可刷新计数器,计数重新开始。 都支持两种启动方式:硬件启动方式和软件启动方式。 都支持两种中断复位产生条件:一种是计数器计数产生下溢;一种是在刷新允许区间之外执行刷新动作, 产生刷新错误。 专用看门狗计数器(SWDT)的时钟源是固定10KHz的LRC,通用看门狗计数器(WDT)的时钟源是PCLK3。   3.例程 3.1.专用看门狗计数器(SWDT) 设置软件启动SWDT,并以约0.62秒进行一次喂狗操作,正常启动情况下LED_BLUE闪烁;按下按键K5则触发错误区间刷新动作,导致SWDT触发复位动作,SWDT触发复位后LED_RED常亮。 #define EXAMPLE_PERIPH_WE (LL_PERIPH_GPIO | LL_PERIPH_EFM | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU) #define EXAMPLE_PERIPH_WP (LL_PERIPH_EFM | LL_PERIPH_FCG) #define SWDT_COUNT_PERIOD (256U) static void SWDT_Config(void) { stc_swdt_init_t stcSwdtInit; /* SWDT configuration */ stcSwdtInit.u32CountPeriod = SWDT_CNT_PERIOD256; stcSwdtInit.u32ClockDiv = SWDT_CLK_DIV32; stcSwdtInit.u32RefreshRange = SWDT_RANGE_0TO25PCT; stcSwdtInit.u32LPMCount = SWDT_LPM_CNT_STOP; stcSwdtInit.u32ExceptionType = SWDT_EXP_TYPE_RST; (void)SWDT_Init(&stcSwdtInit); } int32_t main(void) { uint16_t u16CmpVal; uint32_t u32ResetSrc = 0UL; /* Peripheral registers write unprotected */ LL_PERIPH_WE(EXAMPLE_PERIPH_WE); /* Configure BSP */ BSP_IO_Init(); BSP_LED_Init(); BSP_KEY_Init(); /* Get RMU information */ if (SET == RMU_GetStatus(RMU_FLAG_SWDT)) { u32ResetSrc = RMU_FLAG_SWDT; BSP_LED_On(LED_RED); } RMU_ClearStatus(); /* Configure SWDT */ SWDT_Config(); /* First reload counter to start SWDT */ SWDT_FeedDog(); /* Wait for SWDT module to complete initial */ DDL_DelayMS(10U); /* Count period=256, range=0%-25% */ u16CmpVal = SWDT_COUNT_PERIOD / 4U; /* Peripheral registers write protected */ LL_PERIPH_WP(EXAMPLE_PERIPH_WP); for (;;) { if (SET == BSP_KEY_GetStatus(BSP_KEY_5)) { u16CmpVal = SWDT_COUNT_PERIOD / 2U; } if (SWDT_GetCountValue() < u16CmpVal) { SWDT_FeedDog(); /* Wait for the count value to update */ DDL_DelayMS(10U); if (0UL == u32ResetSrc) { BSP_LED_Toggle(LED_BLUE); } } } }   3.2.通用看门狗计数器(WDT) 设置软件启动WDT,并设置约1.05秒触发一次WDT计数溢出中断,通过按键K5循环切换工作模式(正常模式、睡眠模式),正常模式LED_BLUE闪烁,睡眠模式LED_RED闪烁。 #define EXAMPLE_PERIPH_WE (LL_PERIPH_GPIO | LL_PERIPH_EFM | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU) #define EXAMPLE_PERIPH_WP (LL_PERIPH_EFM | LL_PERIPH_FCG) #define WDT_INT_SRC (INT_SRC_WDT_REFUDF) #define WDT_IRQ_NUM (INT006_IRQn) static __IO uint8_t u8ExtIntCount = 0U; static void WDT_IrqCallback(void) { en_flag_status_t enFlagSta; DDL_DelayUS(30); enFlagSta = WDT_GetStatus(WDT_FLAG_UDF); /* WDT underflow interrupt */ if (SET == enFlagSta) { (void)WDT_ClearStatus(WDT_FLAG_UDF); /* Normal mode */ if (0U == u8ExtIntCount) { BSP_LED_Toggle(LED_BLUE); } else { /* Sleep mode */ BSP_LED_Toggle(LED_RED); } } WDT_FeedDog(); } void BSP_KEY_KEY5_IrqCallback(void) { u8ExtIntCount++; if (u8ExtIntCount >= 2U) { u8ExtIntCount = 0U; } BSP_LED_Off(LED_RED); BSP_LED_Off(LED_BLUE); } static void WDT_Config(void) { stc_wdt_init_t stcWdtInit; stc_irq_signin_config_t stcIrqSignConfig; /* WDT configuration */ stcWdtInit.u32CountPeriod = WDT_CNT_PERIOD16384; stcWdtInit.u32ClockDiv = WDT_CLK_DIV512; stcWdtInit.u32RefreshRange = WDT_RANGE_0TO100PCT; stcWdtInit.u32LPMCount = WDT_LPM_CNT_CONT; stcWdtInit.u32ExceptionType = WDT_EXP_TYPE_INT; (void)WDT_Init(&stcWdtInit); /* Interrupt configuration */ stcIrqSignConfig.enIntSrc = WDT_INT_SRC; stcIrqSignConfig.enIRQn = WDT_IRQ_NUM; stcIrqSignConfig.pfnCallback = &WDT_IrqCallback; (void)INTC_IrqSignIn(&stcIrqSignConfig); NVIC_ClearPendingIRQ(stcIrqSignConfig.enIRQn); NVIC_SetPriority(stcIrqSignConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT); NVIC_EnableIRQ(stcIrqSignConfig.enIRQn); } int32_t main(void) { /* Peripheral registers write unprotected */ LL_PERIPH_WE(EXAMPLE_PERIPH_WE); /* Configure BSP */ BSP_IO_Init(); BSP_LED_Init(); BSP_KEY_Init(); /* Configure WDT */ WDT_Config(); /* First reload counter to start WDT */ WDT_FeedDog(); /* Peripheral registers write protected */ LL_PERIPH_WP(EXAMPLE_PERIPH_WP); for (;;) { /* Sleep mode */ if (1U == u8ExtIntCount) { PWC_SLEEP_Enter(PWC_SLEEP_WFI); } else { /* Reserved */ } } }   4.运行结果 4.1.专用看门狗计数器(SWDT) 按下复位按键复位芯片,LED_BLUE闪烁;按下按键K5触发错误刷新动作;看门狗复位,LED_RED常亮。 [localvideo]7a8c4660524a47427035374f81b2e6d8[/localvideo]   4.2.通用看门狗计数器(WDT) 按下复位按键复位芯片,进入正常模式LED_BLUE闪烁;按下按键K5切换工作状态到睡眠模式,LED_RED闪烁;再次按下按键K5切换工作状态到正常模式,LED_BLUE闪烁。 [localvideo]0bf284fb473f090beed0c7d4d97ac7d1[/localvideo]

统计信息

已有459人来访过

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

留言

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


现在还没有留言