jennyzhaojie

  • 2021-03-01
  • 回复了主题帖: 【RISC-V MCU CH32V103测评】W25Q16读写及应用

    peter91688 发表于 2021-2-28 22:09 很有实用价值哦,感谢感谢

  • 2021-02-28
  • 回复了主题帖: 【RISC-V MCU CH32V103测评】W25Q16读写及应用

    Jacktang 发表于 2021-2-28 10:35 看来外挂的外挂的W25Q16也照样用
    没错!

  • 发表了主题帖: 【RISC-V MCU CH32V103测评】W25Q16读写及应用

    在老版的CH32V103开发板上带有W25Q16存储器,可存放图库和字库等相对固定的数据内容。而在新版的开发板上,该器件被去除了,但我们不妨为它配上一个外挂的W25Q16模块来使用。 模块的接口电路如图1所示: 图1 模块接口电路   在老版的开发板上,W25Q16的读写电路如图2所示,为此我们可以为片选引脚CS添加一个10K的上拉电阻。 图2  板上W25Q16读写电路   外挂模块与开发板的连接形式如图3所示: 图3 外挂模块连接   具体的引脚连接关系为:     CS   —— PA2     DO   —— PA6(SPI1_MISO)     WP   —— 3.3V     DI   —— PA7(SPI1_MOSI)     CLK  —— PA5(SPI1_SCK)     HOLD —— 3.3V   测试程序可直接使用厂家提供的例程,其主程序如下: int main(void) {          u8 datap[SIZE];          u16 Flash_Model;          Delay_Init();          USART_Printf_Init(115200);          printf("SystemClk:%d\r\n",SystemCoreClock);          SPI_Flash_Init();          Flash_Model = SPI_Flash_ReadID();          switch(Flash_Model)          {                   case W25Q80:                        printf("W25Q80 OK!\r\n");                        break;                   case W25Q16:                        printf("W25Q16 OK!\r\n");                        break;                  case W25Q32:                      printf("W25Q32 OK!\r\n");                        break;                   case W25Q64:                        printf("W25Q64 OK!\r\n");                        break;                   case W25Q128:                        printf("W25Q128 OK!\r\n");                        break;                   default:                        printf("Fail!\r\n");                   break;          }          printf("Start Erase W25Qxx....\r\n");          SPI_Flash_Erase_Sector(0);          printf("W25Qxx Erase Finished!\r\n");          Delay_Ms(500);          printf("Start Read W25Qxx....\r\n");          SPI_Flash_Read(datap,0x0,SIZE);          printf("%s\r\n", datap );          Delay_Ms(500);          printf("Start Write W25Qxx....\r\n");          SPI_Flash_Write((u8*)TEXT_Buf,0,SIZE);          printf("W25Qxx Write Finished!\r\n");          Delay_Ms(500);          printf("Start Read W25Qxx....\r\n");          SPI_Flash_Read(datap,0x0,SIZE);          printf("%s\r\n", datap );          while(1); }   有程序可以看出,它不但对W25Q16有效,而且几乎对整个W25Q效率都是有效的。 经读写验证,其效果如图4所示,说明验证成功。有了这个基础,我们就可以为开发板构建一个自己的字库了。 图4 读写效果

  • 2021-02-26
  • 回复了主题帖: 开工大吉,抢楼有礼!预测:2021年电子热门关键词

    在嵌入式MCU上跑AI应用应该会更加流行

  • 回复了主题帖: 开工大吉,抢楼有礼!预测:2021年电子热门关键词

    汽车应用的雷达毫米波技术

  • 回复了主题帖: 【RISC-V MCU CH32V103测评】UART串行通讯

    freebsder 发表于 2021-2-25 22:30 串口的设置应该都是一样的吧,抄来改改就好了。
    但必须去实践和测试!

  • 2021-02-21
  • 发表了主题帖: 【RISC-V MCU CH32V103测评】UART串行通讯

    CH32V103有3个串口,分别是USART1、USART2及USART3,所占用的引脚如下: USART1 TX-->A.9   RX-->A.10 USART2 TX-->A.2   RX-->A.3 USART3 TX-->B.10  RX-->B.11 在通常的情况下,USART1作调试信息输出口,其它2个串口作通讯功能用。 此外,在使用过程它又分为以查询方式接受和以中断方式接收。 最近在一个朋友的项目中要用到3个串行口,且需要以中断方式进行接收,为此打算以CH32V103来解决它。 作为中断方式接收在例程中有使用2个串口的示例,因此关键的是解决第3个串口的中断接收问题,也就是解决USART1中断接收的问题。 经过努力,该问题得到了较好地解决,其测试连接和效果如图1至图3所示。 图1  测试线路连接   图2  双串口通信测试   图3  UART1中断接收测试   3个串口的中断接收初始化函数为: void USART_Printf_Init(uint32_t baudrate) {   GPIO_InitTypeDef GPIO_InitStructure;   USART_InitTypeDef USART_InitStructure; #if (DEBUG == DEBUG_UART1)   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   GPIO_Init(GPIOA, &GPIO_InitStructure); #elif (DEBUG == DEBUG_UART2)   RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   GPIO_Init(GPIOA, &GPIO_InitStructure); #elif (DEBUG == DEBUG_UART3)   RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   GPIO_Init(GPIOB, &GPIO_InitStructure); #endif   USART_InitStructure.USART_BaudRate = baudrate;   USART_InitStructure.USART_WordLength = USART_WordLength_8b;   USART_InitStructure.USART_StopBits = USART_StopBits_1;   USART_InitStructure.USART_Parity = USART_Parity_No;   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;   USART_InitStructure.USART_Mode = USART_Mode_Tx; #if (DEBUG == DEBUG_UART1)   USART_Init(USART1, &USART_InitStructure);   USART_Cmd(USART1, ENABLE); #elif (DEBUG == DEBUG_UART2)   USART_Init(USART2, &USART_InitStructure);   USART_Cmd(USART2, ENABLE); #elif (DEBUG == DEBUG_UART3)   USART_Init(USART3, &USART_InitStructure);   USART_Cmd(USART3, ENABLE); #endif } 3个串口的中断接收引脚配置化函数为: void USARTx_CFG(void) {     GPIO_InitTypeDef  GPIO_InitStructure;     USART_InitTypeDef USART_InitStructure;     NVIC_InitTypeDef  NVIC_InitStructure;     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2|RCC_APB1Periph_USART3, ENABLE);     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_GPIOB , ENABLE);     /* USART1 TX-->A.9   RX-->A.10 */     //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;     //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     //GPIO_Init(GPIOA, &GPIO_InitStructure);     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;     GPIO_Init(GPIOA, &GPIO_InitStructure);     /* USART2 TX-->A.2   RX-->A.3 */     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     GPIO_Init(GPIOA, &GPIO_InitStructure);    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;     GPIO_Init(GPIOA, &GPIO_InitStructure);     /* USART3 TX-->B.10  RX-->B.11 */     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     GPIO_Init(GPIOB, &GPIO_InitStructure);     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;     GPIO_Init(GPIOB, &GPIO_InitStructure);     USART_InitStructure.USART_BaudRate = 115200;     USART_InitStructure.USART_WordLength = USART_WordLength_8b;     USART_InitStructure.USART_StopBits = USART_StopBits_1;     USART_InitStructure.USART_Parity = USART_Parity_No;     USART_InitStructure.USART_HardwareFlowControl =    USART_HardwareFlowControl_None;     USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;     USART_Init(USART1, &USART_InitStructure);     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);     USART_Init(USART2, &USART_InitStructure);     USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);     USART_Init(USART3, &USART_InitStructure);     USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);     NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;     NVIC_Init(&NVIC_InitStructure);     NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;     NVIC_Init(&NVIC_InitStructure);     NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;     NVIC_Init(&NVIC_InitStructure);     USART_Cmd(USART1, ENABLE);     USART_Cmd(USART2, ENABLE);     USART_Cmd(USART3, ENABLE); } 主程序的内容为: int main(void) {     uint8_t i;     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);     Delay_Init();     USART_Printf_Init(115200);//115200     printf("SystemClk:%d\r\n",SystemCoreClock);     printf("USART Interrupt TEST! \r\n");     USARTx_CFG();      Rxfinish0=0;     while(1)     {               if(Rxfinish0==1)               {                      Rxfinish0=0;                      TxCnt0=0;                      while(TxCnt0<10)                      {                          USART_SendData(USART1, RxBuffer0[TxCnt0++]);                          while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);                      }                      RxCnt0=0;                      //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);               }     } }  

  • 2021-02-18
  • 回复了主题帖: 【RISC-V MCU CH32V103测评】BH1750光强检测

    w494143467 发表于 2021-2-17 14:51 感谢分享,期待后续的测评计划帖子哈,我也会持续关注你的哈!!!

  • 2021-02-15
  • 回复了主题帖: 【RISC-V MCU CH32V103测评】BH1750光强检测

    本帖最后由 jennyzhaojie 于 2021-2-15 10:20 编辑
    bigbat 发表于 2021-2-15 08:51 为啥非要使用IO口来模拟IIC,硬件上不是有IIC吗?这种用法在任务少的时候没有问题,但是在多任务的环境下这 ...
    主要是易于移植,使用引脚不受限制;对于容量大的好上系统,小的会受限些。

  • 发表了主题帖: 【RISC-V MCU CH32V103测评】BH1750光强检测

    BH1750是一款数字式光强度传感器,相较于光敏电阻与A/D转换器所构成的光强检测,基于使用简便无需进行标度处理等特点。 BH1750是采用I2C接口来工作的,在使用时,可通过2个I/O口来模拟I2C通讯来进行环境光的检测。 BH1750与开发板的连接及显示效果如下图所示: 在模拟I2C通讯的过程中,对其输出高低电平及读取输入信号的相关定义如下: #define SCL_Set() GPIO_WriteBit(GPIOA, GPIO_Pin_11, Bit_SET) #define SCL_Clr() GPIO_WriteBit(GPIOA, GPIO_Pin_11, Bit_RESET)   #define SDA_Set() GPIO_WriteBit(GPIOA, GPIO_Pin_12, Bit_SET) #define SDA_Clr() GPIO_WriteBit(GPIOA, GPIO_Pin_12, Bit_RESET) 配置BH1750相关引脚的初始化函数为: void BH1750_Init(void) {     GPIO_InitTypeDef  GPIO_InitStructure;                //定义一个GPIO_InitTypeDef类型的结构体     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能与LED相关的GPIO端口时钟     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12; //配置GPIO引脚     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     //设置GPIO模式为推挽输出     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;    //设置GPIO口输出速度   GPIO_Speed_50MHz     GPIO_Init(GPIOA, &GPIO_InitStructure);               //调用库函数,初始化GPIOA } 将相关引脚设置为输入功能的函数为: void IIC_INPUT_MODE_SET() {     GPIO_InitTypeDef  GPIO_InitStructure;                //定义一个GPIO_InitTypeDef类型的结构体     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能与LED相关的GPIO端口时钟     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;            //配置GPIO引脚     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;        //设置GPIO模式为输入  GPIO_Mode_IPD GPIO_Mode_IPU     GPIO_InitStructure.GPIO_Speed =GPIO_Speed_10MHz ;    //设置GPIO口输出速度  GPIO_Speed_50MHz     GPIO_Init(GPIOA, &GPIO_InitStructure);               //调用库函数,初始化GPIOA } 将相关引脚设置为输出功能的函数为: void IIC_OUTPUT_MODE_SET() {     GPIO_InitTypeDef  GPIO_InitStructure;                //定义一个GPIO_InitTypeDef类型的结构体     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能与LED相关的GPIO端口时钟     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;            //配置GPIO引脚     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     //设置GPIO模式为推挽输出     GPIO_InitStructure.GPIO_Speed =GPIO_Speed_10MHz ;    //设置GPIO口输出速度GPIO_Speed_50MHz     GPIO_Init(GPIOA, &GPIO_InitStructure);               //调用库函数,初始化GPIOA } BH1750的多字节读取函数为: void Multiple_Read_BH1750() {     BH1750_Start();     BH1750_SendByte(SlaveAddress+1);     BH1750_RecvACK();     BUF[0] = BH1750_RecvByte();     BH1750_SendACK(0);     BUF[1] = BH1750_RecvByte();     BH1750_SendACK(1);     BH1750_Stop();     Delay_Ms(5); } 读取光强度值得函数为: void Get_Sunlight_Value() {     int dis_data=0;     float temp;     char i=0;     int sd;     Single_Write_BH1750(0x01);  // power on     Single_Write_BH1750(0x10);  // H- resolution mode     Delay_Ms(180);     Multiple_Read_BH1750();     for(i=0;i<3;i++)    dis_data=BUF[0];     dis_data=(dis_data<<8)+BUF[1];     temp=(float)dis_data/1.2;     sd=(int)temp;     if(sd<54612) OLED_ShowNum(0,2,sd,5,16); } 实现显示效果的主程序为: int main(void) {     uint8_t  senflag;     Delay_Init();   //延时函数初始化     app_OLED_Init();     OLED_Init();     OLED_Clear();     OLED_ShowString(0,0,"CH32V103 TEST",16);     OLED_ShowString(0,2,"OLED & BH1750",16);     BH1750_Init();     Delay_Ms(2000);     OLED_Clear();     OLED_ShowString(0,0,"Sunlight=",16);     OLED_ShowString(48,2,"lx",16);     while(1)     {        Get_Sunlight_Value();        Delay_Ms(500);     } }  

  • 2021-02-09
  • 发表了主题帖: 【RISC-V MCU CH32V103测评】DHT22温湿度测量

    本帖最后由 jennyzhaojie 于 2021-2-9 17:47 编辑 DHT22是一款数字式温湿度传感器,相较于热敏式的传感器具有无需A/D转换器参与、无需进行线性化处理等优势。 DHT22采用的是一种单总线式的结构,由此只需一个I/O口就可模拟工作方式来检测环境的温湿度变化。 DHT22与开发板的连接及显示效果如下图所示: DHT22连接及检测效果图   由于DHT22是以单总线进行工作,故对其输出高低电平及读取输入信号的引脚定义如下: #define DHT22_D0_H  GPIOB->BSHR = GPIO_Pin_4  #define DHT22_D0_L  GPIOB->BCR = GPIO_Pin_4 #define DHT22_D0_R  GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_4) 因DHT22在工作时,要在输入与输出模式间切换,故所用的引脚输入和输出模式配置函数如下: void DHT22_IO_IN(void) {     GPIO_InitTypeDef  GPIO_InitStructure;     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;     GPIO_InitStructure.GPIO_Speed =GPIO_Speed_10MHz ;    GPIO_Init(GPIOB, &GPIO_InitStructure); } void DHT22_IO_OUT(void) {     GPIO_InitTypeDef  GPIO_InitStructure;     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     GPIO_InitStructure.GPIO_Speed =GPIO_Speed_10MHz ;     GPIO_Init(GPIOB, &GPIO_InitStructure); } 对DHT22进行数据读取的函数为: uint8_t DHT22_Read_Data(uint8_t *temp,uint8_t *humi) {     uint8_t buf[5];     uint8_t i;     DHT22_Rst();     if(DHT22_Check()==0)     {         for(i=0;i<5;i++)         {             buf=DHT22_Read_Byte();         }         if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])         {            *humi=(buf[0]*256+buf[1])/10;            *temp=(buf[2]*256+buf[3])/10;         }     }else return 1;     return 0; } 对DHT22所用引脚PB4进行初始化的函数为: uint8_t DHT22_Init(void) {     GPIO_InitTypeDef  GPIO_InitStructure;     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;     GPIO_Init(GPIOB, &GPIO_InitStructure);     DHT22_Rst();     return DHT22_Check(); } 实现图示效果的主程序为: int main(void) {     uint8_t  senflag;     Delay_Init();     senflag=DHT22_Init();     Delay_Us(250);     app_OLED_Init();     OLED_Init();     OLED_Clear();     OLED_ShowString(0,0,"CH32V103 TEST",16);     OLED_ShowString(0,2,"OLED & DHT22",16);     Delay_Ms(2000);     OLED_Clear();     while(1)     {         if(!senflag)         {          DHT22_Read_Data(&temperature,&humidity);          OLED_ShowString(0,0,"Temp:   C",16);          OLED_ShowNum(40,0,temperature,2,16);          OLED_ShowString(0,2,"Humi:   %",16);          OLED_ShowNum(40,2,humidity,2,16);          GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);          Delay_Ms(100);          GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);          Delay_Ms(100);         }     } } 以此为基础我们还可以为它配上按键来设置控制参数,进而通过继电器等来控制相应的读取来调节温湿度。

  • 2021-02-07
  • 回复了主题帖: 【RISC-V MCU CH32V103测评】RTC电子时钟

    okhxyyo 发表于 2021-2-6 21:23 赞!!谢谢分享~~要是能拍个小视频就更好了
    有时间拍一个

  • 回复了主题帖: 【RISC-V MCU CH32V103测评】RTC电子时钟

    qwqwqw2088 发表于 2021-2-6 21:03 支持一下 加油

  • 2021-02-06
  • 发表了主题帖: 【RISC-V MCU CH32V103测评】RTC电子时钟

    本帖最后由 jennyzhaojie 于 2021-2-6 16:48 编辑 在CH32V103的内部配置了RTC计时器,把它与OLED显示屏结合起来就能构成一个RTC电子时钟。 实现电子时钟的主程序如下: int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); Delay_Init(); RTC_Init(); OLED_IO_Init(); OLED_Init(); OLED_Clear(); OLED_ShowString(0,0,"CH32V103",16); OLED_ShowString(0,2,"OLED & RTC",16); Delay_Ms(1000); Delay_Ms(1000); OLED_Clear(); OLED_ShowString(0,0,"20 - -",16); OLED_ShowString(0,2," : :",16); while(1) { OLED_ShowNum(16,0,calendar.w_year,2,16); OLED_ShowNum(40,0,calendar.w_month,2,16); OLED_ShowNum(64,0,calendar.w_date,2,16); OLED_ShowNum(16,2,calendar.hour,2,16); OLED_ShowNum(40,2,calendar.min,2,16); OLED_ShowNum(64,2,calendar.sec,2,16); Delay_Ms(1000); } } 相应的RTC初始化函数为: u8 RTC_Init(void) {          u8 temp=0;          RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);          PWR_BackupAccessCmd(ENABLE);          if(BKP_ReadBackupRegister(BKP_DR1) != 0xA1A1)          {                   BKP_DeInit();                   RCC_LSEConfig(RCC_LSE_ON);                   while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET&&temp<250)                   {                           temp++;                           Delay_Ms(20);                   }                   if(temp>=255)return 1;                   RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);                   RCC_RTCCLKCmd(ENABLE);                   RTC_WaitForLastTask();                   RTC_WaitForSynchro();                   RTC_ITConfig(RTC_IT_SEC, ENABLE);                   RTC_WaitForLastTask();                   RTC_EnterConfigMode();                   RTC_SetPrescaler(32767);                   RTC_WaitForLastTask();                   RTC_Set(2021,1,25,2,18,01);              /* Setup Time */                   RTC_ExitConfigMode();                   BKP_WriteBackupRegister(BKP_DR1, 0XA1A1);          }          else          {                  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);                  PWR_WakeUpPinCmd(DISABLE);                  RTC_WaitForSynchro();                  //RTC_ITConfig(RTC_IT_ALR, ENABLE);                  RTC_ITConfig(RTC_IT_SEC, ENABLE);                  RTC_WaitForLastTask();          }          RTC_NVIC_Config();          RTC_Get();          return 0; } 经程序编译下载后,其运行效果如图所示。 RTC电子时钟图    

  • 2021-02-02
  • 回复了主题帖: 【RISC-V MCU CH32V103测评】驱动OLED屏显示

    freebsder 发表于 2021-2-2 15:56 谢谢分享!显示屏的繁琐操作令人厌烦。
    哈哈,在单片机和ARM上使用显示屏还算方便些,若换在FPGA上那就有些头大了,真称得上麻烦的。

  • 回复了主题帖: 【RISC-V MCU CH32V103测评】驱动OLED屏显示

    w494143467 发表于 2021-2-2 16:51 看这个屏幕有点像华大开发板上的屏幕哈~感谢分享!!!

  • 发表了主题帖: 【RISC-V MCU CH32V103测评】驱动OLED屏显示

    OLED屏是一种小巧的显示器件,其面对LCD1602等液晶显示屏也毫不逊色,显示的内容也并不少。此外,它按接口方式可分为I2C接口和SPI接口等,所占用的引脚也不多于LCD1602等。 这里选用的是I2C接口的OLED屏,它最有特点,用2个I/O口就能完成显示任务。 在掌握GPIO口使用的基础上,就可十分轻松地实现驱动OLED屏显示的目标。 这里的OLED屏与MCU的连接关系为: SCL ---PA2 SDA--- PA3 驱动OLED屏所定义的输出高低电平的语句定义为: #define SCL_high GPIO_WriteBit(GPIOA, GPIO_Pin_2, Bit_SET) #define SCL_low  GPIO_WriteBit(GPIOA, GPIO_Pin_2, Bit_RESET) #define SDA_high GPIO_WriteBit(GPIOA, GPIO_Pin_3, Bit_SET) #define SDA_low  GPIO_WriteBit(GPIOA, GPIO_Pin_3, Bit_RESET) 配置2个引脚为输出功能的函数为: void OLED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure;  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  GPIO_Init(GPIOA,&GPIO_InitStructure);  GPIO_SetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_3); } 辅助驱动的相关函数为: void IIC_Start() {    SCL_high;    SDA_high;    SDA_low;    SCL_low; } void IIC_Stop() {  SCL_low;    SDA_low;    SCL_high;    SDA_high; } void IIC_Wait_Ack() {     SCL_high;     SCL_low; } OLED屏的初始化函数为: void OLED_Init(void) {     SCL_high;     SDA_high;     Delay_Ms(800);     OLED_WR_Byte(0xAE,OLED_CMD);//--display off     OLED_WR_Byte(0x40,OLED_CMD);//--set start line address     OLED_WR_Byte(0xB0,OLED_CMD);//--set page address     OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction     OLED_WR_Byte(0x81,OLED_CMD); // contract control     OLED_WR_Byte(0xFF,OLED_CMD);//--128     OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap     OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverse     OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)     OLED_WR_Byte(0x1F,OLED_CMD);//--1/32 duty     OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset     OLED_WR_Byte(0x00,OLED_CMD);//     OLED_WR_Byte(0xD5,OLED_CMD);//set osc division     OLED_WR_Byte(0xf0,OLED_CMD);//     OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period     OLED_WR_Byte(0x22,OLED_CMD);//     OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion     OLED_WR_Byte(0x02,OLED_CMD);//     OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh     OLED_WR_Byte(0x49,OLED_CMD);//     OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable     OLED_WR_Byte(0x14,OLED_CMD);//     OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel     OLED_Clear(); } 显示字符串的函数为: void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t Char_Size) {     unsigned char j=0;     while (chr[j]!='\0')     {       OLED_ShowChar(x,y,chr[j],Char_Size);            x+=8;            if(x>120){x=0;y+=2;}            j++;     } } 实现显示功能的主程序为: int main(void) {     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);     Delay_Init();     OLED_IO_Init();     OLED_Init();     OLED_Clear();     OLED_ShowString(0,0,"CH32V103",16);     OLED_ShowString(0,2,"OLED TEST",16);     while(1) ; } 经编译下载,其运行结果如下图所示。  运行效果图

  • 回复了主题帖: 【RISC-V MCU CH32V103测评】更换PWM输出通道调节LED灯

    okhxyyo 发表于 2021-2-2 09:34 赞!谢谢分享~~期待后面更多精彩内容!
    感谢您的鼓励和支持!

  • 回复了主题帖: 【RISC-V MCU CH32V103测评】更换PWM输出通道调节LED灯

    freebsder 发表于 2021-2-1 22:57 谢谢分享!期待后续!

  • 2021-02-01
  • 发表了主题帖: 【RISC-V MCU CH32V103测评】更换PWM输出通道调节LED灯

    上一次介绍了用TIM1的CH1通道来控制LED灯产生呼吸灯效果,并提出来一个如何迁移PWM输出口的问题。 那如何来实现呢? 请见下图: 也就是说,我们只需改变输出的通道即可。要输出到PA9就选取CH2,要输出到PA10就选取CH3。 道理是好说,关键是该如何做呢? 遍寻TIM1_PWMOut_Init()函数也没见到CH1的影子呀! void TIM1_PWMOut_Init( u16 arr, u16 psc, u16 ccp ) {     GPIO_InitTypeDef GPIO_InitStructure;     TIM_OCInitTypeDef TIM_OCInitStructure;     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE );     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     GPIO_Init( GPIOA, &GPIO_InitStructure );    TIM_TimeBaseInitStructure.TIM_Period = arr;     TIM_TimeBaseInitStructure.TIM_Prescaler = psc;     TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;     TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;     TIM_TimeBaseInit( TIM1, &TIM_TimeBaseInitStructure); #if (PWM_MODE == PWM_MODE1)     TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; #elif (PWM_MODE == PWM_MODE2)     TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; #endif    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;     TIM_OCInitStructure.TIM_Pulse = ccp;     TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;     TIM_OC1Init( TIM1, &TIM_OCInitStructure );     TIM_CtrlPWMOutputs(TIM1, ENABLE );     TIM_OC1PreloadConfig( TIM1, TIM_OCPreload_Disable );     TIM_ARRPreloadConfig( TIM1, ENABLE );     TIM_Cmd( TIM1, ENABLE ); } 经仔细观察,虽为找到CH1,却寻到了除TIM1之外还含有1的痕迹,原来它没有直接以CHx通道的形式给出,而是采用了相关函数调用的方式。 要变为CH2的通道输出,就调用函数TIM_OC2Init( TIM1, &TIM_OCInitStructure )和TIM_OC1PreloadConfig( TIM1, TIM_OCPreload_Disable );而要变为CH3的通道输出,就调用函数TIM_OC3Init( TIM1, &TIM_OCInitStructure )和TIM_OC3PreloadConfig( TIM1, TIM_OCPreload_Disable )。 难道这样修改就可以了吗? 让事实来说话吧,答案是否定的。 那又是为什么呢? 请上眼主函数,其内容如下: int main(void) {      u16 pwmval=0;      u8 a=1;      Delay_Init();      USART_Printf_Init(115200);      printf("SystemClk:%d\r\n",SystemCoreClock);      TIM1_PWMOut_Init( 899, 0, 500 );      while(1)      {          Delay_Ms(10);          if(a) pwmval++;          else  pwmval--;          if(pwmval >300) a =0;          if(pwmval==0) a =1;          TIM_SetCompare1(TIM1, pwmval);      } } 关键就出在对功能没有实际价值的printf输出上,它可是实实在在地在占用PA9和PA10呀!将它删除,再运行程序一切搞定!有时BUG就在你眼皮底下,但可能要花半天的时间才能恍然大悟,原来如此。

最近访客

< 1/2 >

统计信息

已有26人来访过

  • 芯币:379
  • 好友:--
  • 主题:19
  • 回复:47
  • 课时:--
  • 资源:--

留言

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


现在还没有留言