首页 > 其他分享 >stm32学习总结:5、Proteus8+STM32CubeMX+MDK仿真串口并使用串口打印日志(注意重定向printf到串口打印的问题)

stm32学习总结:5、Proteus8+STM32CubeMX+MDK仿真串口并使用串口打印日志(注意重定向printf到串口打印的问题)

时间:2024-01-08 16:37:02浏览次数:26  
标签:MDK BEGIN CODE END void 打印 Private USER 串口


stm32学习总结:5、Proteus8+STM32CubeMX+MDK仿真串口并使用串口打印日志(注意重定向printf到串口打印的问题)


文章目录

  • stm32学习总结:5、Proteus8+STM32CubeMX+MDK仿真串口并使用串口打印日志(注意重定向printf到串口打印的问题)
  • 一、前言
  • 二、资料收集
  • 三、注意事项
  • 四、STM32CubeMX配置
  • 五、MDK工程相关代码
  • 1、非中断方式的按键处理
  • 2、开关机业务
  • 3、printf重定向到串口打印
  • 4、日志打印封装
  • 六、Proteus项目配置
  • 七、仿真测试结果
  • 八、最后


一、前言

上一节模拟实现了串口收发打印,一般我们裸机打印日志通过串口或者JLINK工具等带的RTT打印,对于仿真,我们选择使用串口打印再合适不过了,这里总结一下重定向printf到串口打印日志的过程;期间,尝试了CLion+arm gcc的方式,发现stm32f10x的flash还是支撑不起来未裁剪的标准库,只要使用stdio相关标准库编译时就很容易flash超标。

二、资料收集

https://blog.51cto.com/u_13682052/5670642

STM32串口使用printf打印日志:
https://community.st.com/t5/stm32-mcus-products/how-to-get-printf-example-working-in-another-project/m-p/392014

https://community.st.com/t5/stm32-mcus-products/stm32g0-redirect-printf-to-write-and-use-uart-how-to/m-p/66318

三、注意事项

如果是使用arm gcc编译器的,尽量不要使用printf,这会引入标准库,而对应库不像mdk的microlib做了裁剪,它是比较占用flash的,而stm3210x的flash最多只有32KB,很容易在编译时出现section .rodata’ will not fit in region FLASH'也就是超出flash范围的问题:

stm32学习总结:5、Proteus8+STM32CubeMX+MDK仿真串口并使用串口打印日志(注意重定向printf到串口打印的问题)_#define


网上所说的修改xxx.ld配置文件这些方法很多时候是无效的,不能盲目去修改flash配置。

可以使用比如RTT打印等方式来打印日志,也可以换一些资源比较丰富的板子,也许官方可以出一些裁剪过的利用arm-none-eabi gcc编译的标准库(后面有机会的话我会来尝试一下,用stm32F10x的话arm gcc基本上没办法用printf,引入标准库加上一两个简单的外设接口就肯定会flash超标,用mdk原有的编译器就不会有这个问题)。

四、STM32CubeMX配置

这次彻底精简一下相关配置:

  • 1、一个按钮BUTTON,PA1配置GPIO OUTPUT用来接入按钮,使用默认配置即可,默认低电平,未拉高拉低,添加用户标签BUTTON:

stm32学习总结:5、Proteus8+STM32CubeMX+MDK仿真串口并使用串口打印日志(注意重定向printf到串口打印的问题)_嵌入式硬件_02

  • 2、五个LED,PA4-PA8配置GPIO OUTPUT用来接入LED,使用默认配置即可,默认低电平,未拉高拉低,添加用户标签LED_1到LED_5:

stm32学习总结:5、Proteus8+STM32CubeMX+MDK仿真串口并使用串口打印日志(注意重定向printf到串口打印的问题)_嵌入式硬件_03

  • 3、开启USART1,PA9\PA10来作为打印的串口,配置只发送,波特率设置为9600,不需要配置全局中断,我们使用该串口作为打印串口,只需要发送即可,所以不需要配置中断方式来接收:

stm32学习总结:5、Proteus8+STM32CubeMX+MDK仿真串口并使用串口打印日志(注意重定向printf到串口打印的问题)_stm32_04


然后生成代码即可。

五、MDK工程相关代码

1、非中断方式的按键处理

通过读取IO口的电平判断是否按下按钮,之后通过全局变量确认按下松开以及长短按,这种方式在理解上比较直观(按键这里的处理逻辑是判断LED灯1的电平变化来确定是否开关机,开关机的逻辑我们通过控制LED灯的亮灭来展示):

#include "gpio.h"
#include "key.h"
#include "pwr.h"
//#include "log.h"

// 按键的键值
#define KEY_Press 1

// 读取IO口的电平
#define KEY_PWR HAL_GPIO_ReadPin(GPIOA, BUTTON_Pin)

uint8_t key_old, count;

uint8_t ScanKey(void)
{
    if (GPIO_PIN_RESET == KEY_PWR) {
        HAL_Delay(40);//延时10-20ms,防抖

        if (GPIO_PIN_SET == KEY_PWR) {
            count++;
            return KEY_Press;
        }
    } else {
        HAL_Delay(40);
    }

    return 0;
}

void DealKey(void)
{
    uint8_t key_value = 0;
    //获取键值
    key_value = ScanKey();

    if (key_value != key_old) {
        //与上一次的键值比较 如果不相等,表明有键值的变化,开始计时
        key_old = key_value;
        count = 0;
    } else {
        //如果没有键值的改变 说明没有新按键按下或松开
        key_value = 0;
    }

    if (key_value)// 短按处理
    {
        switch(key_value) {
            case 1 : {
                //LOG(LOG_DEBUG, "KEY1 switch");
                if (GPIO_PIN_SET == HAL_GPIO_ReadPin(GPIOA, LED_1_Pin)) {
                    //LOG(LOG_DEBUG, "pwr on");
                    PWROn();
                } else {
                    //LOG(LOG_DEBUG, "pwr off");
                    PWROff();
                    key_old = key_value;
                }
            }
                break;
            case 2 : {
//                LOG(DEBUG, "KEY2 switch");
                }
                break;
        }

        key_value = 0;
    }
    
    return;
}
#ifndef __KEY_H
#define __KEY_H

#include "main.h"

void DealKey(void);

#endif

2、开关机业务

这里暂时通过LED灯亮灭来模拟,后续可增加底板电路的控制、蜂鸣器的控制等,基本都是通过控制IO口高低电平方式来控制的:

#include "pwr.h"
#include "log.h"
#include "gpio.h"

void TurnOnLED(int flag)
{
    switch(flag)
    {
        case 1:
            HAL_GPIO_WritePin(GPIOA, LED_1_Pin, GPIO_PIN_RESET);
            break;
        case 2:
            HAL_GPIO_WritePin(GPIOA, LED_2_Pin, GPIO_PIN_RESET);
            break;
        case 3:
            HAL_GPIO_WritePin(GPIOA, LED_3_Pin, GPIO_PIN_RESET);
            break;
        case 4:
            HAL_GPIO_WritePin(GPIOA, LED_4_Pin, GPIO_PIN_RESET);
            break;
        case 5:
            HAL_GPIO_WritePin(GPIOA, LED_5_Pin, GPIO_PIN_RESET);
            break;
    }
}

void TurnOffLED(int flag)
{
    switch(flag)
    {
        case 1 :
            HAL_GPIO_WritePin(GPIOA, LED_1_Pin, GPIO_PIN_SET);
            break;
        case 2 :
            HAL_GPIO_WritePin(GPIOA, LED_2_Pin, GPIO_PIN_SET);
            break;
        case 3 :
            HAL_GPIO_WritePin(GPIOA, LED_3_Pin, GPIO_PIN_SET);
            break;
        case 4 :
            HAL_GPIO_WritePin(GPIOA, LED_4_Pin, GPIO_PIN_SET);
            break;
        case 5 :
            HAL_GPIO_WritePin(GPIOA, LED_5_Pin, GPIO_PIN_SET);
            break;
    }
}

void PWROn(void)
{
    LOG(LOG_DEBUG, "PWROn LED blink...");
    for (int i = 1; i< 6; i++) {
        HAL_Delay(100);
        TurnOnLED(i);
    }
}

void PWROff(void)
{
    LOG(LOG_DEBUG, "PWROn LED off...");
    for (int i = 1; i< 6; i++) {
        HAL_Delay(100);
        TurnOffLED(i);
    }
}
#ifndef __PWR_H
#define __PWR_H

#include "main.h"

void PWROn(void);

void PWROff(void);

#endif

3、printf重定向到串口打印

通过stm32的官方论坛和一些参考文章发现是通过对printf进行重写来将发送到终端输出设备的内容通过串口发送出来,不同的编译器链接的库的printf底层调用方式可能有差异,需要注意一下。目前官方论坛上给到的方式是通过宏PUTCHAR_PROTOTYPE控制,我尝试去寻找对应printf的源码,mdk库的printf源码没有找到,据网上说其裁剪的标准库实现的printf是用fputc来将字符发送出去的,而gun c标准库的printf最终查看源码发现是通过调用write函数写入到显示设备的,而该函数为系统调用,系统通过驱动调用硬件IO口去控制显示设备将写入的内容显示,对于没有系统的stm32裸机来说其封装了一个__io_putchar的类似系统调用(其文件名字就叫syscalls.c)接口来让我们重写输出方式,这样我们重写PUTCHAR_PROTOTYPE即可,目前在main.c中添加对应宏控制并重写将写入的ch字符通过串口写入:

#ifdef __GNUC__

/* With GCC, small printf (option LD Linker->Libraries->Small printf

  set to 'Yes') calls __io_putchar() */

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)

#else

#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

#endif /* __GNUC__ */

PUTCHAR_PROTOTYPE

{

    /* Place your implementation of fputc here */

    /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */

    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);

    return ch;

}

整体main.c,大循环中调用按钮监听处理:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "key.h"
#include "stdio.h"

/* USER CODE BEGIN 0 */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#ifdef __GNUC__

/* With GCC, small printf (option LD Linker->Libraries->Small printf

  set to 'Yes') calls __io_putchar() */

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)

#else

#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

#endif /* __GNUC__ */

PUTCHAR_PROTOTYPE
{
    /* Place your implementation of fputc here */

    /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */

    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);

    return ch;
}
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    DealKey();
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#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
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* 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) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

4、日志打印封装

然后我们将printf函数稍微封装一下,也可以使用easylogger日志库:

#include "log.h"
#include "usart.h"

char* get_log_level_str(const int level)
{
	if (level == LOG_DEBUG) {
		return "DEBUG";
	}
	else if (level == LOG_INFO) {
		return "INFO";
	}
	else if (level == LOG_WARN) {
		return "WARN";
	}
	return "UNLNOW";
}

void my_log(const int level,const char* fun, const int line ,const char* fmt, ...)
{
#ifdef OPEN_LOG
	va_list arg;
	va_start(arg, fmt);
	char buf[50] = { 0 };
	vsnprintf(buf, sizeof(buf), fmt, arg);
	va_end(arg);
	if (level >= LOG_LEVEL)
		printf("[%-5s] [%-20s%4d] %s \r\n", get_log_level_str(level), fun, line, buf);
#endif
}
#ifndef __LOG_H_
#define __LOG_H_

#include <stdarg.h>
#include <stdio.h>
#define OPEN_LOG 1
#define LOG_LEVEL LOG_DEBUG

typedef enum
{
	LOG_DEBUG = 0,
	LOG_INFO,
	LOG_WARN
}E_LOGLEVEL;

void my_log(const int level, const char* fun, const int line, const char* fmt, ...);
#define LOG(level,fmt,...) my_log(level,__FUNCTION__,__LINE__,fmt, ##__VA_ARGS__)

#endif

这样我们调用LOG()进行日志打印就可以了,和常规软件开发的日志打印接口基本就一致了。

六、Proteus项目配置

Proteus创建串口和虚拟终端、LED灯、电阻灯我们之前已经总结过了,不再重复,这里再添加一个按键即可,按下P,搜索BUTTON即可添加,之后按如下方式接线:

stm32学习总结:5、Proteus8+STM32CubeMX+MDK仿真串口并使用串口打印日志(注意重定向printf到串口打印的问题)_#define_05


串口TX、RX和之前接法一样,还需要配置其波特率,也和之前一样,虚拟终端这里有一些区别,上节我们是TX、RX是和串口对应一致的,但是这里我们要显示串口发送的内容,所以RX接入串口的TX,不要搞错了,而且由于是显示日志的打印串口,我们配置的只发送,所以理论上RX是可以不接的。至于其它的接线基本没有什么注意的,和之前的大体一致,主要注意控制开关的高低电平即可,一端接电源,另一端设置低电平即导通,电流流过。

七、仿真测试结果

按下按键根据key.c中的处理逻辑就会来回判断进行开关机业务处理了,这里模拟开关机通过LED灯的亮灭来展示,串口的TX发送接入虚拟终端RX将发送的日志直接显示出来了,串口工具在Windows上打开对端的串口也是可以看到对应的信息的(快去试一下吧):

stm32学习总结:5、Proteus8+STM32CubeMX+MDK仿真串口并使用串口打印日志(注意重定向printf到串口打印的问题)_#include_06

八、最后

下一节我们来试下ADC和蜂鸣器的使用吧,蜂鸣器这种简单的音频提示元器件也是用的比较广泛的,比较常见的像小区的门禁基本都会加蜂鸣器提示刷卡是否成功等,ADC接口则常常用来读取一些传感器的信息或者电压信息等,也是比较常用的。最近的一些总结基本都是用为主,对于这些IO口的更深层次的配置及控制原理我们暂时不做深入分析,只需要了解怎么用即可,这些东西感觉总结C51的时候来分析总结更合适一些,C51的应用相对简单一些,STM32的应用开发已经比较接近Linux应用开发这种层级,很多时候不用太考虑底层的实现,只需要会用接口开发比较复杂的应用即可(所以这种应用开发实时操作系统的学习就比较重要了),等到解决一些疑难杂症时,再对其做深入了解和理解,新手直接深入容易被劝退。


标签:MDK,BEGIN,CODE,END,void,打印,Private,USER,串口
From: https://blog.51cto.com/xiaoyaoyou10/9146693

相关文章

  • 经典算法问题之打印日期
    这也是一道经典的算法题。其实也是用两个数组。还有判断是否闰年。两个个循环,外面一个是月份循环,内部一个是每个月的天数循环,然后计数器Count++就行,直到和天数相同就跳出循环,打印就行。#include<stdio.h>intjudge(intyear){if(year%400==0||year%100!=......
  • 云打印有什么优势?云打印的优点有哪些?
    伴随着互联网的发展,云打印技术也逐渐成熟。目前,云打印正受到广大用户的热烈追捧。那么云打印有什么优势?云打印的优点有哪些?今天小易就带大家来了解一下。 云打印有什么优势?云打印的优点有哪些?云打印是指有打印需求的用户通过互联网上传打印需求,云服务器接受打印需求后......
  • vi / vim 键盘图(清晰打印版,桌面背景好图)
    PDFFilehttps://files.cnblogs.com/files/RioTian/vivim-graphical.zip?t=1704439837&download=true程序员定制版(on-screen150DPI)程序员定制版(colorhard-copy300DPI)程序员定制版(monochromehard-copy300DPI),下载打印版程序员定制版(colorblindhard-copy))**,下载打印......
  • 串口光猫技术解析:高效数据传输的关键
    在数字通信的世界中,串口光猫技术以其高效的数据传输能力,已成为现代信息社会的关键组成部分。这项技术将传统的串行通信方式与现代的光纤通信技术相结合,为用户提供了一个高速且可靠的网络连接解决方案。一、串口光猫的核心作用串口光猫(光纤猫),全称为光纤网络终端,是一种用于将光信号转......
  • 不展现报表直接打印
    不展现直接打印可以考虑这么几种方式: 1、如果使用自带demo下的jsp,可以把展现报表的div设置为隐藏,点击打印按钮可以打印;如果按钮都不想点,看下toolbar.jsp内打印按钮的js函数,在jsp末尾调用一下就行了。 2、使用自带demo下的jsp访问报表,浏览器查看“网页源代码”,可以找......
  • unigui+fastReport实现web打印方案(77)
    简单一点的(05)UniGUI何输出FastReport的pdf新建一个打印预览uniForm窗口printU 主窗口引用它,新建一个unibutton打印按钮. usesprintU;procedureTMainForm.UniButton1Click(Sender:TObject);beginprintU.UniForm1.ShowModal(nil);end;  usesServerModule;proced......
  • PSoc62™开发板之串口通信
    实验目的1.使用串口和PC机通信:接收和发送信息2.接收GNSS模块定位信息实验准备PSoc62™开发板CH340USB转TTL模块ATGM332DGNSS模块公母头杜邦线x4板载资源板载有多少uart创建工程例程,在libraries/HAL_Drivers/uart_config.h中查看BSP支持的uart数量及对应的GPIO,可以看......
  • 打印一个二进制数的奇数位和偶数位
    #define_CRT_SECURE_NO_WARNINGS1#include<stdio.h>intbin_two(inta){ intcount=0; printf("奇数位为:"); for(inti=30;i>=0;i-=2)//32位右移30位就可以得到32位内所有奇数位二进制数 { printf("%d",(a>>i)&1); } printf("\n&q......
  • 打印一个二进制数的奇数位和偶数位
    #define_CRT_SECURE_NO_WARNINGS1#include<stdio.h>intbin_two(inta){ intcount=0; printf("奇数位为:"); for(inti=30;i>=0;i-=2)//32位右移30位就可以得到32位内所有奇数位二进制数 { printf("%d",(a>>i)&1); } printf("\n&q......
  • 多线程循环打印123
    1、多线程循环打印123importjava.util.concurrent.locks.Condition;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;publicclassPrintThread{privateLocklock=newReentrantLock();privatevolatileintflag......