donatello1996

  • 2019-03-15
  • 回复了主题帖: 联想栗子开发板评测活动获奖名单~

    谢谢管管谢谢EE谢谢栗子社区谢谢栗子:pleased:确认信息无误

  • 2019-03-12
  • 加入了学习《正点原子手把手教你学STM32-M7》,观看 STM32学习方法+视频说明

  • 2019-02-24
  • 回复了主题帖: 下载、评论赢双重好礼|PI 邀您跟littleshrimp一起拆解小米最新二合一充电宝

           首先是充电宝充电方式由原来的microUSB转为市电接口,这是一种革新,目前没有别家充电宝在小米之前做出这种方案,不过为啥要把microUSB舍弃掉呢,这个我就非常不解,我觉得两种充电方式共存最好。       输出5V3A中规中矩,如果之后推出5V4A就更上一层楼了。       由于我不懂模电,因此对QC协议和【INN2215K 是一款集成了 650 V MOSFET、同步整流、反馈和恒功率特性的适合USB-PD 和 QC 3.0 应用的离线式反激恒压/恒流开关 IC】这些知识点一脸懵逼,直接跳过。      【电池背面丝印为 ZMJ F8216AUBN 的 IC 网上说是紫米电子自己定制的一款单片机没找到资料,应该是用于电池温度检测、电池电量检测、LED 驱动等功能。】这个总算是稍微懂一点,就是一个专门应用与电池电量管理应用的单片机,并且还是定制的。       最后作者还实际用万用表来测试快充效果,确实很666,主要是因为我家的充电宝没有快充功能所以很羡慕。

  • 2019-01-28
  • 发表了主题帖: 【Nucleo G071评测】最终结项

         最终结项是结合QT上位机程序一起使用的,上位机程序采用串口通信,原理与串口助手大同小异只是做了一些简单的按钮用于控制下位机即G0板子,如框图所示,做了一个控制照明灯和三色RGB灯的按钮,以及采集温湿度和光照强度的进度条: 打开串口之后能接收到实时的温湿度和光照强度信息: 通过按钮控制LED照明灯和三色RGB灯: OLED上也是实时显示温湿度和光照强度信息: 上传上位机工程文件和G0板子工程文件:

  • 2019-01-27
  • 发表了主题帖: 【Nucleo G071评测】接上串口LORA模块进行实验&远程控制继电器

    本帖最后由 donatello1996 于 2019-1-27 23:18 编辑     原计划中需要用到两个LORA模块进行无线串口数据透传,大致的框图如下,仅仅是做了一个非常简单的示意图:     G0板子和CH340串口模块都连上LORA模块,两个LORA模块配置好通信的频率信道等,通过串口与G0板子和CH340模块通信,并且为了加强信号,两个LORA模块均使用5V供电,插上专用天线:         CH340模块连接电脑,可虚拟成串口:            G0板子单独供电,进行透传工作: 使用语句 sprintf(s,"%.1f℃ %.1f%%\n",temper_value,humi_value); UART1_Send_String(s); 并循环执行,可在虚拟串口终端打印温湿度信息: 光检测不够,再做个控制,如远程控制一个继电器,在中断处理函数中加入代码,检测电脑端串口LORA模块发出的数据,第5个字节的数据即rx_buf[4]控制PD6引脚电平,PD6上再接一个继电器,就可以实现远程控制继电器,为1则控制继电器闭合,为2则控制继电器断开: void UART_DMA_Get() {         if(recv_end_flag==1)         {                 recv_end_flag=0;                 //printf("rx_buf=%s\n",rx_buf);                 if(rx_buf[0]==0x01)                 {                         TIM3->CCR1=rx_buf[1];                         TIM3->CCR3=rx_buf[2];                         TIM3->CCR4=rx_buf[3];                         if(rx_buf[4]==0x01)                                 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_6,0);                         else if(rx_buf[4]==0x02)                                 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_6,1);                 }         }         HAL_UART_Receive_DMA(&huart1,(unsigned char*)rx_buf,BUFFERSIZE); }

  • 发表了主题帖: 【Nucleo G071评测】检测HTS221温湿度传感器数据

         庆科的扩展板上带有HTS221温湿度传感器,传感器走I2C总线,与之前的OLED屏幕共用总线,这个传感器啥都好,精度和采集速率要比DHT11快得多,就是工作方式是插值型,写程序计算数值有一丁点的繁杂: #define HTS221_ADDRESS                              0xBE #define HTS221_RES_CONF_ADDR                        0x10 #define HTS221_CTRL_REG1_ADDR                       0x20 #define HTS221_CTRL_REG2_ADDR                       0x21 #define HTS221_HUMIDITY_OUT_L_ADDR                  0x28 #define HTS221_H0_RH_X2_ADDR                        0x30 #define HTS221_H1_RH_X2_ADDR                        0x31 #define HTS221_T0_degC_X8_ADDR                      0x32 #define HTS221_T1_degC_X8_ADDR                      0x33 #define HTS221_T1_T0_MSB_X8_ADDR                    0x35 #define HTS221_H0_T0_OUT_L_ADDR                     0x36 #define HTS221_H1_T0_OUT_L_ADDR                     0x3A #define HTS221_T0_OUT_L_ADDR                        0x3C #define HTS221_T1_OUT_L_ADDR                        0x3E unsigned char buffer[4]; float t0,t1,h0,h1,humi_value=0,temper_value=0; short t0out,t1out,h0out,h1out,humi_temp=0,temper_temp=0; int HTS221_Init() {         I2C_GPIO_Init();         if(I2C_ReadData(0xbe,0x0f)==0xbc)         {                 I2C_WriteData(0xbe,0x80,HTS221_CTRL_REG1_ADDR);//启动                 I2C_WriteData(0xbe,0x03,HTS221_RES_CONF_ADDR);                 return 0;         }         return -1; } float mapFloat(int x,int in_min,int in_max,float out_min,float out_max) {   return (x-in_min)*(out_max-out_min)/(in_max-in_min)+out_min; } void HTS221_Read() {         I2C_WriteData(HTS221_ADDRESS,0x01,HTS221_CTRL_REG2_ADDR);         buffer[0]=I2C_ReadData(HTS221_ADDRESS,HTS221_HUMIDITY_OUT_L_ADDR);         buffer[1]=I2C_ReadData(HTS221_ADDRESS,HTS221_HUMIDITY_OUT_L_ADDR+1);         buffer[2]=I2C_ReadData(HTS221_ADDRESS,HTS221_HUMIDITY_OUT_L_ADDR+2);         buffer[3]=I2C_ReadData(HTS221_ADDRESS,HTS221_HUMIDITY_OUT_L_ADDR+3);                 temper_temp=((int)(buffer[3]<<8)|buffer[2]);         humi_temp=((int)(buffer[1]<<8)|buffer[0]);                 temper_value=mapFloat(temper_temp,t0out,t1out,t0,t1);         humi_value=mapFloat(humi_temp,h0out,h1out,h0,h1);         } void HTS221_Calibration() {         buffer[0]=I2C_ReadData(HTS221_ADDRESS,HTS221_T0_degC_X8_ADDR);         buffer[1]=I2C_ReadData(HTS221_ADDRESS,HTS221_T0_degC_X8_ADDR+1);         buffer[2]=I2C_ReadData(HTS221_ADDRESS,HTS221_T0_degC_X8_ADDR+2);         buffer[3]=I2C_ReadData(HTS221_ADDRESS,HTS221_T0_degC_X8_ADDR+3);                         int t0degCx8 = ((int)(buffer[3]&0x03)<<8)|buffer[0];   int t1degCx8 = ((int)(buffer[3]&0x0c)<<6)|buffer[1];                 t0=t0degCx8/8.0;         t1=t1degCx8/8.0;                 buffer[0]=I2C_ReadData(HTS221_ADDRESS,HTS221_T0_OUT_L_ADDR);         buffer[1]=I2C_ReadData(HTS221_ADDRESS,HTS221_T0_OUT_L_ADDR+1);         buffer[2]=I2C_ReadData(HTS221_ADDRESS,HTS221_T0_OUT_L_ADDR+2);         buffer[3]=I2C_ReadData(HTS221_ADDRESS,HTS221_T0_OUT_L_ADDR+3);                           t0out=((int)(buffer[1]<<8)|buffer[0]);   t1out=((int)(buffer[3]<<8)|buffer[2]);         buffer[0]=I2C_ReadData(HTS221_ADDRESS,HTS221_H0_RH_X2_ADDR);         buffer[1]=I2C_ReadData(HTS221_ADDRESS,HTS221_H0_RH_X2_ADDR+1);           unsigned char h0RHx2 = buffer[0];   unsigned char h1RHx2 = buffer[1];         h0 = h0RHx2/2.0;         h1 = h1RHx2/2.0;         buffer[0]=I2C_ReadData(HTS221_ADDRESS,HTS221_H0_T0_OUT_L_ADDR);         buffer[1]=I2C_ReadData(HTS221_ADDRESS,HTS221_H0_T0_OUT_L_ADDR+1);         h0out=((int)(buffer[1]<<8)|buffer[0]);         buffer[0]=I2C_ReadData(HTS221_ADDRESS,HTS221_H1_T0_OUT_L_ADDR);         buffer[1]=I2C_ReadData(HTS221_ADDRESS,HTS221_H1_T0_OUT_L_ADDR+1);           h1out = ((int)(buffer[1]<<8)|buffer[0]); } 这里需要注意,HTS221的out数值和temp临时数值是两个八位寄存器的数值拼在一起的,所以必须使用short型数据类型,不然正负符号位会被当成数 据位,即原本是负数的数值成了整数。HTS221需要在进行插值计算中间值完毕之后才可以进行最终温湿度数据的计算。 观察效果:

  • 2019-01-25
  • 回复了主题帖: 瑞萨电子RL78/G11目标板免费申请活动【50元京东卡获奖名单】

    50卡获奖确认,信息无误

  • 2019-01-24
  • 发表了主题帖: 【Nucleo G071评测】PWM呼吸灯

        评测一个开发板的定时器功能,最简单的方式就是评测它的呼吸灯功能,呼吸灯是由PWM波实现的,PWM则是由定时器产生的。     打开CubeMX初始化PC6 PC8 PC9三个引脚,分别映射为定时器3的CH1 CH3 CH4通道,用于驱动RGB灯的三个引脚,设置定时器3不分频(即分频值为0),独立时钟,计数值为100上限: 调好了之后就可以直接接RGB灯了,初始化函数如下: void TIM3_Init() {         GPIO_InitTypeDef GPIO_InitStruct;      __HAL_RCC_GPIOC_CLK_ENABLE();   __HAL_RCC_TIM3_CLK_ENABLE();           GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_8|GPIO_PIN_9;   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;   GPIO_InitStruct.Pull = GPIO_NOPULL;   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;   GPIO_InitStruct.Alternate = GPIO_AF1_TIM3;   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);           htim3.Instance = TIM3;   htim3.Init.Prescaler = 0;   htim3.Init.CounterMode = TIM_COUNTERMODE_UP;   htim3.Init.Period = 100;   htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;   htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;   HAL_TIM_PWM_Init(&htim3);   sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;   HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig);   sConfigOC.OCMode = TIM_OCMODE_PWM1;   sConfigOC.Pulse=0;   sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;   sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;   HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);         HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3);   HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_4);         HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);         HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3);         HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_4);                 TIM3->CCR1=0;         TIM3->CCR3=0;         TIM3->CCR4=0;        } 通过TIM3的CCRX寄存器来修改三个通道的占空比:                 TIM3->CCR1=0;                 TIM3->CCR3=0;                 TIM3->CCR4=0;                        for(i=0;i<=100;i++)                 {                         TIM3->CCR1=i;                         Delay_ms(5);                 }                 Delay_ms(500);                 for(i=100;i>=0;i--)                 {                         TIM3->CCR1=i;                         Delay_ms(5);                 }                 for(i=0;i<=100;i++)                 {                         TIM3->CCR3=i;                         Delay_ms(5);                 }                 Delay_ms(500);                 for(i=100;i>=0;i--)                 {                         TIM3->CCR3=i;                         Delay_ms(5);                 }                 for(i=0;i<=100;i++)                 {                         TIM3->CCR4=i;                         Delay_ms(5);                 }                 Delay_ms(500);                 for(i=100;i>=0;i--)                 {                         TIM3->CCR4=i;                         Delay_ms(5);                 } 看看效果:

  • 发表了主题帖: 【Nucleo G071评测】I2C OLED&AD采集

        借助一块庆科出品的Arduino扩展板,插上Nucleo-G071板子之后,可以继续进行接下来的传感器实验。     首先是这块扩展板是自带了I2C接口的OLED扩展模块,占用接口为PB8 PB9,直接用模拟I2C时序进行通信即可: void OLED_WR_Byte(uint8_t data,char cmd) {         if(cmd)         {                 // HAL_I2C_Mem_Write(&hi2c1,0x78,0x40,1,&data,1,10);                 I2C_WriteData(0x78,data,0x40);         }   else         {                 //HAL_I2C_Mem_Write(&hi2c1,0x78,0,1,&data,1,10);                 I2C_WriteData(0x78,data,0);         } } void OLED_Set_Pos(char x,char y) {   uint8_t tmp[3] = {0xb0+y, ((x&0xf0)>>4)|0x10, (x&0x0f)|0x01};   OLED_WR_Byte(tmp[0],0);         OLED_WR_Byte(tmp[1],0);         OLED_WR_Byte(tmp[2],0); } void OLED_Clear(void)   {           int i,n;                             for(i=0;i<8;i++)           {                   OLED_WR_Byte(0xb0+i,0);                 OLED_WR_Byte(0x00,0);                 OLED_WR_Byte(0x10,0);                 for(n=0;n<128;n++)OLED_WR_Byte(0,1);         } } void OLED_Fill(void)   {           int i,n;                             for(i=0;i<8;i++)           {                   OLED_WR_Byte(0xb0+i,0);                 OLED_WR_Byte(0x00,0);                 OLED_WR_Byte(0x10,0);                 for(n=0;n<128;n++)OLED_WR_Byte(0xff,1);         } } void OLED_ShowChinese(int x,int y,int n) {         int i=0;         n*=32;         OLED_Set_Pos(x,y);         for(i=n;i<n+16;i++)         {                 OLED_WR_Byte(CnChar,1);         }         OLED_Set_Pos(x,y+1);         for(i=n+16;i<n+32;i++)         {                 OLED_WR_Byte(CnChar,1);         } } void OLED_ShowASCII(int x,int y,char n) {         int i=0,m;         n-=0x20;         m=n*16;         OLED_Set_Pos(x,y);         for(i=m;i<m+8;i++)         {                 OLED_WR_Byte(ASCIIChar,1);         }         OLED_Set_Pos(x,y+1);         for(i=m+8;i<m+16;i++)         {                 OLED_WR_Byte(ASCIIChar,1);         } } void OLED_ShowString(int x,int y,char s[]) {         int i;         for(i=0;s!='\0';i++)                 OLED_ShowASCII(x+i*8,y,s);         } void OLED_Init() {         //I2C1_Init();         I2C_GPIO_Init();   OLED_WR_Byte(0xAE,0);//--turn off oled panel   OLED_WR_Byte(0x00,0);//---set low column address   OLED_WR_Byte(0x10,0);//---set high column address   OLED_WR_Byte(0x40,0);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)   OLED_WR_Byte(0x81,0);//--set contrast control register   OLED_WR_Byte(0xCF,0); // Set SEG Output Current Brightness   OLED_WR_Byte(0xA1,0);//--Set SEG/Column Mapping     0xa0?????????? 0xa1??????   OLED_WR_Byte(0xC8,0);//Set COM/Row Scan Direction   0xc0?????????? 0xc8??????   OLED_WR_Byte(0xA6,0);//--set normal display   OLED_WR_Byte(0xA8,0);//--set multiplex ratio(1 to 64)   OLED_WR_Byte(0x3f,0);//--1/64 duty   OLED_WR_Byte(0xD3,0);//-set display offset        Shift Mapping RAM Counter (0x00~0x3F)   OLED_WR_Byte(0x00,0);//-not offset   OLED_WR_Byte(0xd5,0);//--set display clock divide ratio/oscillator frequency   OLED_WR_Byte(0x80,0);//--set divide ratio, Set Clock as 100 Frames/Sec   OLED_WR_Byte(0xD9,0);//--set pre-charge period   OLED_WR_Byte(0xF1,0);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock   OLED_WR_Byte(0xDA,0);//--set com pins hardware configuration   OLED_WR_Byte(0x12,0);   OLED_WR_Byte(0xDB,0);//--set vcomh   OLED_WR_Byte(0x40,0);//Set VCOM Deselect Level   OLED_WR_Byte(0x20,0);//-Set Page Addressing Mode (0x00/0x01/0x02)   OLED_WR_Byte(0x02,0);//   OLED_WR_Byte(0x8D,0);//--set Charge Pump enable/disable   OLED_WR_Byte(0x14,0);//--set(0x10) disable   OLED_WR_Byte(0xA4,0);// Disable Entire Display On (0xa4/0xa5)   OLED_WR_Byte(0xA6,0);// Disable Inverse Display On (0xa6/a7)         OLED_Clear();   OLED_Set_Pos(0,0);           OLED_WR_Byte(0xAF,0); /*display ON*/ } 录入字库之后看看显示效果: 然后是带了AD采集的光照强度传感器,占用接口为PA4,这里需要通过CubeMX配置ADC接口: 移植官方例程生成的ADC初始化代码: ADC_ChannelConfTypeDef sConfig; ADC_HandleTypeDef hadc1; GPIO_InitTypeDef GPIO_InitStruct; void ADC_Init() {   __HAL_RCC_GPIOA_CLK_ENABLE();   __HAL_RCC_ADC_CLK_ENABLE();   GPIO_InitStruct.Pin = GPIO_PIN_4;   GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;   GPIO_InitStruct.Pull = GPIO_NOPULL;   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);           hadc1.Instance = ADC1;   hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;   hadc1.Init.Resolution = ADC_RESOLUTION_12B;   hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;   hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;   hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;   hadc1.Init.LowPowerAutoWait = DISABLE;   hadc1.Init.LowPowerAutoPowerOff = DISABLE;   hadc1.Init.ContinuousConvMode = DISABLE;   hadc1.Init.NbrOfConversion = 1;   hadc1.Init.DiscontinuousConvMode = DISABLE;   hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;   hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;   hadc1.Init.DMAContinuousRequests = DISABLE;   hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;   hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_1CYCLE_5;   hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_1CYCLE_5;   hadc1.Init.OversamplingMode = DISABLE;   hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;   HAL_ADC_Init(&hadc1); } int ADC1_GetValue()    {            int val;         sConfig.Channel=ADC_CHANNEL_4;   sConfig.Rank = ADC_REGULAR_RANK_1;   sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;         HAL_ADC_ConfigChannel(&hadc1,&sConfig);   if(HAL_ADC_Start(&hadc1)==HAL_OK)         {                 val=(int)HAL_ADC_GetValue(&hadc1);                 return val;         }         else return -1; } 观察效果,光照强度传感器输出的ADC电压值会随着光照强度变化:

  • 2019-01-19
  • 发表了主题帖: 【Nucleo G071评测】SYSTICK&两种常用的低功耗模式对比

        单片机的SYSTICK计时器是非常常用的,这个计时器最厉害的地方在于不管是裸机程序还是RTOS程序,SYSTICK都能用作准确的计时,ARM系统中,在不调用TIM定时器的前提下,SYSTICK是较为理想的计时器,初始化简单,调用也简单。 初始化SYSTICK计时器需要用到一个int型的计时因子: int fac_us; 然后是设置SYSTICK外设的时钟源和分频值: HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); fac_us=64; 写好定时函数: void Delay_us(int nus) {                int temp;         SysTick->LOAD=nus*fac_us;         SysTick->VAL=0x00;         SysTick->CTRL=0x05;         do         {                 temp=SysTick->CTRL;         }         while((temp&0x01)&&!(temp&(1<<16)));         SysTick->CTRL=0x00;         SysTick->VAL=0x00; } void Delay_ms(int nms) {         for(int i=0;i<nms;i++)Delay_us(1000); } 写好中断服务程序: void SysTick_Handler(void) {   HAL_IncTick(); } 然后就是低功耗模式了,低功耗模式与SYSTICK计时器息息相关,因为启用低功耗模式需要关闭SYSTICK运作,首先是不使用任何低功耗模式的运行功耗,G0系列在64MHz主频下,不启用任何外设,运行功耗为53mA。然后是启用睡眠模式,语句为 HAL_SuspendTick(); HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); 第一句为关闭SYSTICK计时器,第二句是启用睡眠模式,可以被中断打断,睡眠电流为45mA: 然后是停止模式 HAL_SuspendTick(); HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); 停止电流为39mA: 待机模式没有进行测试,因为待机模式不算很常用的低功耗模式,并且待机模式恢复起来比较麻烦。 然后是拿F030的Nucleo板子来做横向测量,可以看到F030的运行模式下也是53mA,而G0在64MHz主频下运行电流也是53mA,这就是G0的优势所在了。

  • 2019-01-17
  • 回复了主题帖: 颁奖:瑞萨电子RL78/G11目标板免费申请活动【目标板获奖名单】

    40份京东卡呢?我比较关心这个

  • 2019-01-16
  • 发表了主题帖: 【Nucleo G071评测】串口1空闲中断+DMA实现不定长接收

        经过两天一夜的摸索,总算是搞清楚了G0系列型号的DMA的脾气,可以进行我接下来的串口不定长接收的DEMO。     G0系列的DMA只有一个外设DMA1,DMA1支持7个通道,这7个通道也是非常人性化地可以被任意分配到任何支持DMA传输的外设如串口、ADC、SPI接口等,这点我相信ST是在向NXP新出的RT1050系列学习。也就是说,串口1的RX接收DMA通道,可以是DMA1通道1,也可以是DMA1通道2,甚至可以是DMA1的通道7。由于板上的LPUART1外设已经用作调试打印了,所以我使用串口1即PA9 PA10用来外接串口模块做实验。     首先打开CubeMX,配置串口1以及DMA,如图,可以选择7个通道里面的任意一个,我选了DMA1通道1:     其它参数不变,像FIFO那个就不打开:     在生成的例程中,有一句语句非常重要,由于现在G0系列的DMA没有指定特定外设用特定通道,因此还需要一个DMAMUX控制器用来重映射通道,通俗来讲就是锁定通道,相关配置为DMA_InitTypeDef的Request成员变量,就是这个变量,昨晚折腾了我一晚上,因为CubeMX生成的例程里面默认是没有指定Request变量的:     然后是直接跟随官方配置即可,添加空闲中断检测与响应: void UART1_Init(int baud) {         __HAL_RCC_GPIOA_CLK_ENABLE();   __HAL_RCC_USART1_CLK_ENABLE();         __HAL_RCC_DMA1_CLK_ENABLE();                 GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;   GPIO_InitStruct.Pull = GPIO_PULLUP;   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;   GPIO_InitStruct.Alternate = GPIO_AF1_USART1;   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);           huart1.Instance = USART1;   huart1.Init.BaudRate = baud;   huart1.Init.WordLength = UART_WORDLENGTH_8B;   huart1.Init.StopBits = UART_STOPBITS_1;   huart1.Init.Parity = UART_PARITY_NONE;   huart1.Init.Mode = UART_MODE_TX_RX;   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;   huart1.Init.OverSampling = UART_OVERSAMPLING_16;   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;   huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;   HAL_UART_Init(&huart1);           HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8);   HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8);   HAL_UARTEx_DisableFifoMode(&huart1);         __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);         HAL_NVIC_SetPriority(USART1_IRQn,0,0);   HAL_NVIC_EnableIRQ(USART1_IRQn);                 hdma_usart1_rx.Instance=DMA1_Channel1;   hdma_usart1_rx.Init.Direction=DMA_PERIPH_TO_MEMORY;   hdma_usart1_rx.Init.PeriphInc=DMA_PINC_DISABLE;   hdma_usart1_rx.Init.MemInc=DMA_MINC_ENABLE;   hdma_usart1_rx.Init.PeriphDataAlignment=DMA_PDATAALIGN_BYTE;   hdma_usart1_rx.Init.MemDataAlignment=DMA_MDATAALIGN_BYTE;   hdma_usart1_rx.Init.Mode=DMA_NORMAL;   hdma_usart1_rx.Init.Priority=DMA_PRIORITY_VERY_HIGH;         hdma_usart1_rx.Init.Request=DMA_REQUEST_USART1_RX;   HAL_DMA_Init(&hdma_usart1_rx);   __HAL_LINKDMA(&huart1,hdmarx,hdma_usart1_rx);         HAL_UART_Receive_DMA(&huart1,(unsigned char*)rx_buf,BUFFERSIZE); } 写好中断服务函数,并在主程序中添加循环检测中断响应标志位的函数: void USART1_IRQHandler() {         uint32_t temp;         if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE))         {                 __HAL_UART_CLEAR_IDLEFLAG(&huart1);                 HAL_UART_DMAStop(&huart1);                 temp=__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);                 printf("------%d-----\n",temp);                 rx_len=BUFFERSIZE-temp;                 recv_end_flag=1;         } } void UART_DMA_Get() {         if(recv_end_flag==1)         {                 //rx_len=0;                 recv_end_flag=0;                 printf("rx_buf=%s\n",rx_buf);         }         HAL_UART_Receive_DMA(&huart1,(unsigned char*)rx_buf,BUFFERSIZE); } 连接好硬件电路,即使用一个CH340串口模块连接板子的PA9 PA10: 看看效果:

  • 2019-01-15
  • 回复了主题帖: 下载《ADI 任意波形发生器方案》抢楼有礼啦!

  • 回复了主题帖: Maxim 利用nanoPower创新技术,致力于降低系统的静态功耗,看视频答题赢好礼!颁奖啦

    100京东卡确认,信息无误

  • 发表了主题帖: 【Nucleo G071评测】开箱&介绍&上电&工程环境搭建&点灯&串口

         收到开发板3天,周末外出了,所以现在补回帖子。      这次ST推出G071板子,确实让我眼前一亮,传统Nucleo-64板子的MiniUSB接口被取代为更通用的microUSB接口,可以接现在Nucleo-144板子的线,不过此举有人赞成有人反对,赞成的说是与时俱进,反对的说是,要么别换掉MiniUSB,要么就直接上Type-C,MiniUSB的稳定性要比microUSB高得多,之后ST怎么取舍,就拭目以待了,反正我是挺期待Type-C接口的板子的。然后就是传统Nucleo-64开发板带的一个用户LED,这次G0的板子额外多了个LD3是指示电源信息的,跟Nucleo-144一样。当然,最重要的还是主角STM32G071RB。     G0系列必须使用CubeMX5进行开发,老旧版本CubeMX4已经不支持新型号芯片了,打开CubeMX5并选择G0: 启用LPUART1(PA2 PA3)并设置波特率115200,数据位7: 由原理图看出LD4是PA5,因此初始化PA5引脚: 设置内部晶振倍频到64MHz: 在ST官网下载G0的固件包并解压: 生成基于MDK5的例程: 最后是在MDK官网下载G0的器件支持包并安装: 查看效果: 上传工程文件:

  • 2018-12-25
  • 回复了主题帖: hi,小伙伴们!这里有棵测评许愿树

    1.原子潘多拉IOT开发板 2.NXP RT1060评估板 3.ROCK PI 4 RK3399开发板

  • 回复了主题帖: (全部已安排派送,帖内可查货运单号)联想栗子开发板评测活动入围名单出炉啦~

    已确认能按时完成评测,邮寄信息无误,另外,确认收货地址能在qq或者微信端完成么,我直接跟发出板子的工作人员确认。

  • 回复了主题帖: 【树莓派3B+测评】使用USB摄像头

    我的摄像头比较便宜所以拍出来的图片比较辣鸡。。。你这个是多少钱买的?

  • 2018-12-24
  • 回复了主题帖: EEWorld开发板芯币开始啦!参与竞价赢免单!

    c100

  • 发表了主题帖: 【树莓派3B+测评】安装libjpeg库&驱动USB摄像头

    本帖最后由 donatello1996 于 2018-12-24 09:21 编辑     Linux系统中操作图像的相关函数均可直接通过libjpeg库实现,通过此库可实现BMP转JPG,BMP转FrameBuffer显示,或是FrameBuffer转BMP/JPG保存,在此次实验中,我用libjpeg库实现FrameBuffer直接转为JPG图片。 准备工作,首先下载安装libjpeg库的支持: apt-get install libjpeg8-dev 然后插上USB免驱摄像头,如果能正常驱动的话会在/dev目录下生成video开头的外设: 使用VL42库的相关函数抓取摄像头图片并保存到本地:         if(V4L2_Init((char*)"/dev/video0")!=0)         {             printf("摄像头初始化失败\n");             return 0;         }         V4l2_Grab();         Yuyv_2_RGB888(buffers,frame_buffer);         Encode_Jpeg(frame_buffer,IMAGEWIDTH,IMAGEHEIGHT,(char*)"1.jpg"); V4L2的操作头文件: #ifndef CAMERA_H #define CAMERA_H #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> #include <linux/types.h> #include <linux/videodev2.h> #include <setjmp.h> #include "jpeglib.h" #include "lcd.h" static int fd_video; static struct  v4l2_capability  cap; //V4L2设备信息读结构体对象 struct v4l2_fmtdesc fmtdesc; struct v4l2_format fmt; //V4L2设置捕获信息读写结构体对象 struct v4l2_streamparm setfps; //V4L2设置帧数相关读写结构体对象 struct v4l2_requestbuffers req; //V4L2申请帧缓冲结构体对象 struct v4l2_buffer buf; //V4L2缓存数据结构体对象 enum v4l2_buf_type type; //V4L2采集类型结构体对象 #define  IMAGEWIDTH    640 #define  IMAGEHEIGHT   480 unsigned char frame_buffer[IMAGEWIDTH*IMAGEHEIGHT*3]; typedef struct {     void *start;     unsigned int length; } buffer; buffer *buffers; int V4L2_Init(char * filename) {     int i,ret = 0;     if ((fd_video=open(filename,O_RDWR))==-1)     {         printf("Error opening V4L interface\n");         return (0);     }     if (ioctl(fd_video,VIDIOC_QUERYCAP,&cap) == -1)     {         printf("Error opening device %s: unable to query device.\n",filename);         return (0);     }     else     {          printf("driver:\t\t%s\n",cap.driver);          printf("card:\t\t%s\n",cap.card);          printf("bus_info:\t%s\n",cap.bus_info);          printf("version:\t%d\n",cap.version);          printf("capabilities:\t%x\n",cap.capabilities);          if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == V4L2_CAP_VIDEO_CAPTURE)          {             printf("Device %s: supports capture.\n",filename);         }         if ((cap.capabilities & V4L2_CAP_STREAMING) == V4L2_CAP_STREAMING)         {             printf("Device %s: supports streaming.\n",filename);         }     }     fmtdesc.index=0;     fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;     printf("Support format:\n");     while(ioctl(fd_video,VIDIOC_ENUM_FMT,&fmtdesc)!=-1)     {         printf("\t%d.%s\n",fmtdesc.index+1,fmtdesc.description);         fmtdesc.index++;     }     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;     fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;     fmt.fmt.pix.height = IMAGEHEIGHT;     fmt.fmt.pix.width =  IMAGEWIDTH;     fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;     if(ioctl(fd_video,VIDIOC_S_FMT, &fmt) == -1)     {         printf("Unable to set format\n");         return 1;     }     if(ioctl(fd_video,VIDIOC_G_FMT, &fmt) == -1)     {         printf("Unable to get format\n");         return 2;     }     {          printf("fmt.type:\t\t%d\n",fmt.type);          printf("pix.pixelformat:\t%c%c%c%c\n",fmt.fmt.pix.pixelformat & 0xFF, (fmt.fmt.pix.pixelformat >> 8) & 0xFF, (fmt.fmt.pix.pixelformat >> 16) & 0xFF, (fmt.fmt.pix.pixelformat >> 24) & 0xFF);          printf("pix.height:\t\t%d\n",fmt.fmt.pix.height);          printf("pix.width:\t\t%d\n",fmt.fmt.pix.width);          printf("pix.field:\t\t%d\n",fmt.fmt.pix.field);     }     //set fps     ioctl(fd_video, VIDIOC_G_PARM, &setfps);     //setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;     //setfps.parm.capture.timeperframe.numerator = 30;     //setfps.parm.capture.timeperframe.denominator = 30;     req.count=4;     req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;     req.memory=V4L2_MEMORY_MMAP;     if(ioctl(fd_video,VIDIOC_REQBUFS,&req)==-1)     {         printf("request for buffers error\n");         return 3;     }     printf("init %s \t[OK]\n",filename);     return 0; } int V4l2_Grab() {     unsigned int n_buffers;     buffers =(buffer*)malloc(req.count*sizeof (*buffers));     if (!buffers)     {         printf ("Out of memory\n");         return 0;     }     for (n_buffers = 0; n_buffers < req.count; n_buffers++)     {         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;         buf.memory = V4L2_MEMORY_MMAP;         buf.index = n_buffers;         //query buffers         if (ioctl (fd_video,VIDIOC_QUERYBUF, &buf) == -1)         {             printf("query buffer error\n");             return(0);         }         buffers[n_buffers].length = buf.length;         buffers[n_buffers].start = mmap(NULL,buf.length,PROT_READ |PROT_WRITE, MAP_SHARED,         fd_video, buf.m.offset);         if (buffers[n_buffers].start == MAP_FAILED)         {             printf("buffer map error\n");             return 0;         }     }     for (n_buffers = 0; n_buffers < req.count; n_buffers++)     {         buf.index = n_buffers;         ioctl(fd_video, VIDIOC_QBUF, &buf);     }     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;     ioctl (fd_video, VIDIOC_STREAMON, &type);     ioctl(fd_video, VIDIOC_DQBUF, &buf);     printf("grab yuyv OK\n");     return 1; } int Yuyv_2_RGB888(buffer* input_buffers,unsigned char *output_buffer) {     int i,j,r1,g1,b1,r2,g2,b2;     unsigned char y1,y2,u,v;     unsigned char *pointer;     pointer =(unsigned char*)input_buffers[0].start;     for(i=0;i<IMAGEHEIGHT;i++)     {     for(j=0;j<IMAGEWIDTH/2;j++)     //每次取4个字节,也就是两个像素点,转换rgb,6个字节,还是两个像素点     {     y1 = *( pointer + (i*IMAGEWIDTH/2+j)*4);     u  = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 1);     y2 = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 2);     v  = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 3);     r1 = y1 + 1.042*(v-128);     g1 = y1 - 0.34414*(u-128) - 0.71414*(v-128);     b1 = y1 + 1.772*(u-128);     r2 = y2 + 1.042*(v-128);     g2 = y2 - 0.34414*(u-128) - 0.71414*(v-128);     b2 = y2 + 1.772*(u-128);     if(r1>255)     r1 = 255;     else if(r1<0)     r1 = 0;     if(b1>255)     b1 = 255;     else if(b1<0)     b1 = 0;     if(g1>255)     g1 = 255;     else if(g1<0)     g1 = 0;     if(r2>255)     r2 = 255;     else if(r2<0)     r2 = 0;     if(b2>255)     b2 = 255;     else if(b2<0)     b2 = 0;     if(g2>255)     g2 = 255;     else if(g2<0)     g2 = 0;     *(output_buffer + (i*IMAGEWIDTH/2+j)*6    ) = (unsigned char)b1;     *(output_buffer + (i*IMAGEWIDTH/2+j)*6 + 1) = (unsigned char)g1;     *(output_buffer + (i*IMAGEWIDTH/2+j)*6 + 2) = (unsigned char)r1;     *(output_buffer + (i*IMAGEWIDTH/2+j)*6 + 3) = (unsigned char)b2;     *(output_buffer + (i*IMAGEWIDTH/2+j)*6 + 4) = (unsigned char)g2;     *(output_buffer + (i*IMAGEWIDTH/2+j)*6 + 5) = (unsigned char)r2;     }     }     printf("change to RGB OK \n");     free(input_buffers); } int Encode_Jpeg(unsigned char *lpbuf,int width,int height,char *output_filename) {     struct jpeg_compress_struct cinfo ;     struct jpeg_error_mgr jerr ;     JSAMPROW  row_pointer[1] ;     int row_stride ;     char *buf=NULL ;     int x ;     FILE *fptr_jpg = fopen ((char *)output_filename,"wb");     if(fptr_jpg==NULL)     {     printf("Encoder:open file failed!/n") ;      return 0;     }     cinfo.err = jpeg_std_error(&jerr);     jpeg_create_compress(&cinfo);     jpeg_stdio_dest(&cinfo, fptr_jpg);     cinfo.image_width = width;     cinfo.image_height = height;     cinfo.input_components = 3;     cinfo.in_color_space = JCS_RGB;     jpeg_set_defaults(&cinfo);     jpeg_set_quality(&cinfo, 80,1);     jpeg_start_compress(&cinfo, 1);     row_stride = width * 3;     buf=(char*)malloc(row_stride);     row_pointer[0] =(unsigned char*)buf;     while (cinfo.next_scanline < height)     {      for (x=0;x<row_stride; x+=3)     {     buf[x]   = lpbuf[x];     buf[x+1] = lpbuf[x+1];     buf[x+2] = lpbuf[x+2];     }     jpeg_write_scanlines (&cinfo, row_pointer, 1);     lpbuf += row_stride;     }     jpeg_finish_compress(&cinfo);     fclose(fptr_jpg);     jpeg_destroy_compress(&cinfo);     free(buf);     printf("save \"JPEG\"OK\n");     return 0 ; } int close_v4l2(void) {      if(fd_video!=-1)      {          close(fd_video);          return 1;      }      return 0; } #endif 由于使用了libjpeg,因此在文件编译后面要加-ljpeg选项: 执行,执行完毕之后会在工程目录下生成1.jpg图片:

最近访客

< 1/6 >

统计信息

已有134人来访过

  • 芯币:415
  • 好友:1
  • 主题:35
  • 回复:39
  • 课时:--
  • 资源:--

留言

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


早晨五点 2018-7-13
在吗哥,我想请教您一个问题。我用HAL库的接收中断接收数据为什么接收到的数据总是变换次序?比如第2个数据变成第一个,第三个编程第二个。。。我应该怎么办呢?希望您能帮助我一下
查看全部