最简单DIY基于STM32的远程控制电脑系统②(无线遥杆+按键控制)

news/2024/11/8 22:42:48/

STM32库函数开发系列文章目录

第一篇:STM32F103ZET6单片机双串口互发程序设计与实现
第二篇:最简单DIY基于STM32单片机的蓝牙智能小车设计方案
第三篇:最简单DIY基于STM32F407探索者开发板的MPU6050陀螺仪姿态控制舵机程序
第四篇:最简单DIY基于STM32F407探索者开发板和PCA9685舵机控制模块的红外遥控机械臂控制程序
第五篇:注释最详细、代码最简单的STM32+摄像头+显示屏的颜色跟踪电路软硬件方案
第六篇:最简单DIY基于STM32单片机的WIFI智能小车设计方案
第七篇:最简单DIY基于STM32的远程控制电脑系统①(电容触摸+按键控制)
第八篇:最简单DIY基于STM32的远程控制电脑系统②(无线遥杆+按键控制)


文章目录

  • STM32库函数开发系列文章目录
  • 前言
  • 一、最简单DIY基于STM32的远程控制电脑系统②(无线遥杆+按键控制)是什么?
  • 二、拿来主义日记
    • 1.准备硬件和接线
    • 2.技术点说明
    • 3.资料展示和源码展示
  • 三、运行与调试
  • 四、总结


前言

    daodanjishui物联网核心原创技术之最简单DIY基于STM32的远程控制电脑系统②(无线遥杆+按键控制)。
    市面上有各种开源电脑控制软件和硬件的方案,但是有复杂的有简单的,如果想快速入门STM32控制电脑的软硬件方案,这个方案会给你一个快捷高效的方案。


一、最简单DIY基于STM32的远程控制电脑系统②(无线遥杆+按键控制)是什么?

    我记得本栏的第七篇博文:**最简单DIY基于STM32的远程控制电脑系统①(电容触摸+按键控制)**的设计中大量使用了库函数和别人的开源代码,鲁迅先生的“拿来主义”表现的淋漓尽致,这也是STM32库函数开发的魅力所在,完成了触摸屏和按键控制电脑鼠标。为了实现STM32无线+遥杆控制电脑,所以诞生第八篇博文。
    由于使用STM32单片机与电脑形成有线连接去控制电脑,有点不方便,所以在第八篇中,将推出用无线模块NRF24L01进行无线通信,说白了就是:制作无线鼠标,所以需要用到两块STM32开发板和NRF24L01模块,上位机采用正点原子战舰开发板通过USB数据线与笔记本电脑相连,下位机是德飞莱迷你stm32开发板通过NRF24L01无线模块与上位机进行无线连接。
     由于国内电脑远程控制技术封锁,一些技术和理论都是本人经过摸索实践推敲得出,没有权威性,所以仅供参考。首先要谈到用软件和硬件控制电脑的方案:软件有socket编程和java 鼠标键盘控制sdk开发,硬件有单片机USB鼠标键盘库的使用。下面先介绍ST公司STM32F103ZET6自带的鼠标控制电脑的方案。用到的是正点原子战舰开发板和配套的4.3寸电容触摸屏。最终实现用单片机的触摸屏实现鼠标控制的效果。全家福如下图所示:
在这里插入图片描述
无线模块在每个开发板的左上角,热拔插结构。遥杆模块是用杜邦线连接在德飞莱迷你STM32F103ZET6开发板上的。大的单片机是正点原子战舰开发板。小单片机是用蓝色小充电宝供电,大单片机用电脑USB数据线供电。

B站视频演示地址:https://www.bilibili.com/video/BV1MU4y117aq?t=0.0

视频如下

最简单DIY基于STM32的远程控制电脑系统②(无线摇杆+按键控制)


二、拿来主义日记

1.准备硬件和接线

     硬件需要正点原子开发板和4.3寸配套的电容触摸屏,无线模块在每个开发板的左上角,热拔插结构。遥杆模块是用杜邦线连接在德飞莱迷你STM32F103ZET6开发板上的。大的单片机是正点原子战舰开发板。小单片机是用蓝色小充电宝供电,大单片机用电脑USB数据线供电。由于用到了正点原子的开源代码进行人工二次合成,所以这个方案全部免费,后期我有更猛的代码,可以实现更高级的控制效果,当然后期可能需要收费。后期能做到空中鼠标控制,控制遥杆控制,空中手机控制,控制MPU6050控制, 远程MQTT控制等等。

代码预览截图如下(上位机鼠标发射端代码截图):
在这里插入图片描述

代码预览截图如下(下位机电脑接收端代码截图):
在这里插入图片描述

2.技术点说明

    从视频可以看出,可以灵活使用无线遥杆来控制笔记本电脑的鼠标进行上下左右对角线移动。代码是核心原创的,包括的知识点有:STM32字库编程、STM32电容屏触摸控制和显示、STM32 USB开发、SPI通信技术、NRF24L01无线模块的使用和私人定义无线通信协议的传输和解析、STM32 两路ADC遥杆参数采集、按键电平检测技术、电容屏彩色字体显示、显示屏涂鸦显示和清屏技术等等。
    刚开始调试的时候由于遥杆采集的ADC数据不稳定导致鼠标漂移,后面我采用了有效的方案锁定住鼠标,效果非常不错,所以才有勇气把如此珍贵丝滑的代码分享给大家。有了这套代码,读者可以开发有关电脑鼠标原创控制的项目,下一期我会以ESP8266 AT 固件的方式 和 Arduino SDK二次开发的方式 与STM32单片机构成手机客户端遥控电脑的方案。daodanjishui原创经典值得期待。

3.资料展示和源码展示

    文末尾有下载资料的地址。资料列表如下所示:
在这里插入图片描述

源码如下:(移植了ST公司控制电脑鼠标的库,发射机(无线鼠标))

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "key.h"  
#include "24cxx.h" 
#include "I2C.h"
#include "touch.h" 
#include "usb_lib.h"
#include "hw_config.h"
#include "usb_pwr.h" 
#include "string.h"
#include "mpu6050.h"
#include "spi.h"
#include "24l01.h"
#include "malloc.h"
#include "sdio_sdcard.h"  
#include "w25qxx.h"    
#include "ff.h"  
#include "exfuns.h"   
#include "text.h"		
#include "usart3.h"
#include "fontupd.h" 
#include "adc.h"
/************************************************实验0:ALIENTEK STM32F103开发板工程模板注意,这是手册中的调试章节使用的main文件技术支持:daodanjishui 2022.5.16CSDN博客:https://blog.csdn.net/niruxi0401 作者:daodanjishui
************************************************/
//ALIENTEK Mini STM32开发板范例代码21  二次开发为战舰4.3寸电容屏鼠标触控板
//触摸屏实验  
//技术支持:daodanjishui  	2022.5.16
//增加一个单片机作为遥控器,原来单片机作为接收机
//两个NRF24L01无线模块使用SPI总线控制,分别安装在遥控器和接收机上
//这个代码是单片机遥控代码:鼠标
//加入ADC遥杆控制鼠标 2022.5.29
//遥杆控制鼠标上下左右,遥杆按下是鼠标点击//计算 x1,x2 的绝对值
u32 usb_abs(u32 x1,u32 x2)
{
if(x1>x2)return x1-x2;
else return x2-x1;
}
int main(void)
{ 
//short temp[3];//存放mpu6050数据的数组
//u8 tmp_buf[33];	 //发射寄存器
u8 tmp_buf[33]="The mouse is connection!";
u8 key;
short X=0,Y=0;		 //发送到电脑端的坐标值
u8 keysta=0;
short rollsta=0;  
int i;
//遥杆供电为板载3.3的电压#define GO_speed_p 15     //这个是鼠标移动跨度的灵敏度,可以从0~60的数值进行调整
//#define BACK_speed_p 60
//#define LEFT_speed_p 60
#define RIGHT_speed_p 15float go_mid = 1.62;    //全局变量获取最初静止状态游戏手柄y中位电压值
int go_speed = 0;
//int back_speed = 0;
float turn_mid = 1.69;    //全局变量获取最初静止状态游戏手柄x中位电压值
//int left_speed = 0;
int right_speed = 0;u16 adcx1;u16 adcx2;//u16 temp3;//u16 temp4;float temp1;    //浮点型float temp2;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组设置 
delay_init();  //延时初始化
uart_init(115200); //串口 1 初始化
//LCD_Init();  //初始化液晶
LED_Init(); //LED 初始化
KEY_Init();  //按键初始化
//TP_Init();  //初始化触摸屏 
MYI2C_Init();//I2C初始化
MPU6050_Init();//陀螺仪初始化
//W25QXX_Init();				//初始化W25Q128
usart3_init(115200);		//初始化串口3 
//my_mem_init(SRAMIN);		//初始化内部内存池
//exfuns_init();				//为fatfs相关变量申请内存  
//f_mount(fs[0],"0:",1); 		//挂载SD卡 
//f_mount(fs[1],"1:",1); 		//挂载FLASH.
delay_ms(40);
Adc_Init();
NRF24L01_Init();//24l01初始化while(NRF24L01_Check())	//检测无线模块能否用,否则死循环{printf("未检测到24l01\r\n");delay_ms(200);//无线模块不能用的测试}NRF24L01_TX_Mode();//设置24l01为发射模式//NRF24L01_RX_Mode();//设置24l01为接收模式	NRF24L01_TxPacket(tmp_buf);//发送链接成功的字符串	while(1){		 		key=KEY_Scan(1);if(key==WKUP_PRES)			//WK_UP 退出测试		 { printf("WKUP_PRES");	rollsta=1;//滚轮向上	}else if(key==KEY0_PRES)	//KEY0 向ID0发送数据 {   printf("KEY0_PRES"); keysta|=0X02;					//发送鼠标右键		 }else if(key==KEY1_PRES)	//KEY1 向ID1发送数据 {printf("KEY1_PRES");rollsta=-1;//发送滚轮数据到电脑 向下			}else if(key==KEY2_PRES){printf("KEY2_PRES");keysta|=0X01;					//发送鼠标左键 }else if(keysta||rollsta!=0)//之前有按下{keysta=0; //发送松开命令给电脑rollsta=0;}adcx1=Get_Adc_Average(ADC_Channel_1,10);//通道1采集,采集十个数取平均值,连接PA1temp1=(float)adcx1*(3.3/4096);//12位的最大值是4096if(go_mid-temp1>=0.3)//鼠标后退,这个比较值需要调整一下,免得遥杆静止的时候乱飘go_speed =(go_mid-temp1)*GO_speed_p;//将电压值转为鼠标的位移elsego_speed = (go_mid-temp1)*GO_speed_p;if(usb_abs(go_mid,temp1)>0.3)//防止遥杆静止的时候发生小数据变化	Y=go_speed;elseY=0;adcx2=Get_Adc_Average(ADC_Channel_2,10);//通道2采集,取十个数值的平均值,接PA2temp2=(float)adcx2*(3.3/4096);//12位的最大值是4096if(turn_mid-temp2>=0.3)//鼠标左转right_speed =(turn_mid-temp2)*RIGHT_speed_p;//将电压值转为鼠标的位移elseright_speed =(turn_mid-temp2)*RIGHT_speed_p;if(usb_abs(turn_mid,temp2)>0.3)		X=right_speed;elseX=0;tmp_buf[0]=(u8)keysta;tmp_buf[1]=(u8)((X>>8)&0x00ff);tmp_buf[2]=(u8)(X&0x00ff);tmp_buf[3]=(u8)((Y>>8)&0x00ff);tmp_buf[4]=(u8)(Y&0x00ff);tmp_buf[5]=(u8)rollsta;key=' ';for(i=6;i<32;i++){key++;if(key>('~'))key=' ';tmp_buf[i]=key;}tmp_buf[32]=0;printf("X=%d,Y=%d\n",X,Y);if(NRF24L01_TxPacket(tmp_buf)==TX_OK){int i;for(i=0;i<32;i++){tmp_buf[i]=0;//清空数组}	LED1=0;//德飞莱开发板的LED2发亮}	else   LED1=1;//德飞莱开发板的LED2不亮}
} 

接收机源码:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "key.h"  
#include "24cxx.h" 
#include "touch.h" 
#include "usb_lib.h"
#include "hw_config.h"
#include "usb_pwr.h" 
#include "string.h"
#include "spi.h"
#include "24l01.h"
#include "malloc.h"
#include "sdio_sdcard.h"  
#include "w25qxx.h"    
#include "ff.h"  
#include "exfuns.h"   
#include "text.h"		
#include "usart3.h"
#include "fontupd.h" 
#include "math.h"
/************************************************实验0:ALIENTEK STM32F103开发板工程模板注意,这是手册中的调试章节使用的main文件技术支持:daodanjishui 2022.5.16CSDN博客:https://blog.csdn.net/niruxi0401 作者:daodanjishui
************************************************/
//ALIENTEK Mini STM32开发板范例代码21  二次开发为战舰4.3寸电容屏鼠标触控板
//触摸屏实验  
//技术支持:daodanjishui  	2022.5.16
//增加一个单片机作为遥控器,原来单片机作为接收机
//两个NRF24L01无线模块使用SPI总线控制,分别安装在遥控器和接收机上
//一个正点原子的MPU6050陀螺仪模块使用IIC总线控制,安装在遥控单片机上
//这个接收机的代码优势在于可以通用于:体感+按键鼠标   和  遥杆+按键鼠标 //装载画图界面 
void Load_Draw_Dialog(void)
{
LCD_Clear(WHITE);//清屏
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(lcddev.width-24,0,200,16,16,"RST");//显示清屏区域
POINT_COLOR=RED;//设置画笔蓝色
} 
//计算 x1,x2 的绝对值
u32 usb_abs(u32 x1,u32 x2)
{
if(x1>x2)return x1-x2;
else return x2-x1;
}
int main(void)
{ 
u8 tmp_buf[33];
u8 key;
short X=0,Y=0;		 //发送到电脑端的坐标值
s8 x0,y0; //发送到电脑端的坐标值
u8 keysta=0; 
//[0]:0,左键松开;1,左键按下;
//[1]:0,右键松开;1,右键按下
//[2]:0,中键松开;1,中键按下
u8 tpsta=0;  //0,触摸屏第一次按下;1,触摸屏滑动
int xlast, ylast; //最后一次按下的坐标值
u8 *p;//发送命令的指针
int i;
u16 t=999;		//加速第一次获取链接状态
u8 timex;	//设置循环次数
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组设置 
delay_init();  //延时初始化
uart_init(115200); //串口 1 初始化
LCD_Init();  //初始化液晶
LED_Init(); //LED 初始化
KEY_Init();  //按键初始化
TP_Init();  //初始化触摸屏 
//W25QXX_Init();				//初始化W25Q128
usart3_init(115200);		//初始化串口3 
my_mem_init(SRAMIN);		//初始化内部内存池
//exfuns_init();				//为fatfs相关变量申请内存  
//f_mount(fs[0],"0:",1); 		//挂载SD卡 
//f_mount(fs[1],"1:",1); 		//挂载FLASH.
delay_ms(40);
font_init();			//检查字库是否OK
NRF24L01_Init();//24l01初始化while(NRF24L01_Check())	//检测无线模块能否用,否则死循环{printf("未检测到24l01\r\n");delay_ms(200);//无线模块不能用的测试POINT_COLOR=RED;LCD_ShowString(60,50,200,16,16,"24l01 can not open");}//NRF24L01_TX_Mode();//设置24l01为发射模式
//NRF24L01_RX_Mode();//设置24l01为接收模式
POINT_COLOR=RED;
LCD_ShowString(60,50,200,16,16,"战舰 STM32");
LCD_ShowString(60,70,200,16,16,"USB Mouse TEST");
LCD_ShowString(60,90,200,16,16,"daodanjishui");
LCD_ShowString(60,110,200,16,16,"2022.5.16"); 
LCD_ShowString(60,130,200,16,16,"KEY_UP:SCROLL +  KEY_DOWN:SCROLL -");
//LCD_ShowString(60,130,200,16,16,"KEY_DOWN:SCROLL -");
LCD_ShowString(60,150,200,16,16,"KEY1:RIGHT Button"); 
LCD_ShowString(60,170,200,16,16,"KEY0:LEFT Button");
delay_ms(1800);
USB_Port_Set(0); //USB 先断开
delay_ms(300);
USB_Port_Set(1); //USB 再次连接
USB_Interrupts_Config(); //USB 中断配置
Set_USBClock(); //USB 时钟设置
USB_Init();  //USB 初始化		
Load_Draw_Dialog();while(1){		 NRF24L01_RX_Mode();		  		    		    				 if(NRF24L01_RxPacket(tmp_buf)==0)//一旦接收到信息,则显示出来.{tmp_buf[32]=0;//加入字符串结束符 Show_Str(15,155,180,190,tmp_buf,12,0);//显示接收到的数据 X=(s16)((tmp_buf[1]<<8)|tmp_buf[2]);Y=(s16)((tmp_buf[3]<<8)|tmp_buf[4]);	printf("Button=%d,X=%8d,Y=%8d,SCROLL=%d\r\n",tmp_buf[0],X,Y,tmp_buf[5]);//在串口一打印NRF24L01传输过来的参数	Joystick_Send(tmp_buf[0],X,Y,tmp_buf[5]);				for(i=0;i<32;i++){tmp_buf[i]=0;//清空数组}}				    key=KEY_Scan(0);//按键扫描	if(key==WKUP_PRES)			//WK_UP 退出测试		 { printf("WKUP_PRES");	LCD_ShowString(60,130,200,16,16,"KEY_UP:SCROLL +");			//rollsta=1;//滚轮向上		Joystick_Send(0,0,0,1);	u3_printf("WKUP_PRES\r\n");			}else if(key==KEY0_PRES)	//KEY0 向ID0发送数据 {   printf("KEY0_PRES");keysta|=0X02;					//发送鼠标右键	LCD_ShowString(60,130,200,16,16,"KEY1:RIGHT Button");Joystick_Send(2,0,0,0);}else if(key==KEY1_PRES)	//KEY1 向ID1发送数据 { printf("KEY1_PRES");LCD_ShowString(60,130,200,16,16,"KEY_DOWN:SCROLL -");//rollsta=-1;//发送滚轮数据到电脑  向下	Joystick_Send(0,0,0,(u8)-1);		}else if(key==KEY2_PRES){printf("KEY2_PRES");keysta|=0X01;					//发送鼠标左键 	Joystick_Send(1,0,0,0);	LCD_ShowString(60,130,200,16,16,"KEY0:LEFT Button");}else if(keysta)//之前有按下{keysta=0; //发送松开命令给电脑Joystick_Send(0,0,0,0);}tp_dev.scan(0); //触摸屏扫描if(tp_dev.sta&TP_PRES_DOWN) //触摸屏被按下{//最少移动 5 个单位,才算滑动if(((usb_abs(tp_dev.x[0],xlast)>4)||(usb_abs(tp_dev.y[0],ylast)>4))&&tpsta==0){xlast=tp_dev.x[0]; //记录刚按下的坐标ylast=tp_dev.y[0];tpsta=1;}if(tp_dev.x[0]<lcddev.width&&tp_dev.y[0]<lcddev.height){ if(tp_dev.x[0]>(lcddev.width-24)&&tp_dev.y[0]<16)Load_Draw_Dialog();else{ TP_Draw_Big_Point(tp_dev.x[0],tp_dev.y[0],RED);  //画图 }if(bDeviceState==CONFIGURED){if(tpsta)//滑动{x0=(xlast-tp_dev.x[0])*3;//上次坐标与得到的坐标之差,扩大 2倍y0=(ylast-tp_dev.y[0])*3;xlast=tp_dev.x[0]; //记录刚按下的坐标ylast=tp_dev.y[0];Joystick_Send(keysta,-x0,-y0,0); //发送数据到电脑delay_ms(5);}} }}else { tpsta=0;delay_ms(1); }//清除	if(bDeviceState==CONFIGURED)LED1=0;//USB配置成功,则绿灯亮else LED1=1;if(timex)timex--;if(timex==1)LCD_Fill(30+54,125,239,122,WHITE);//清屏t++;delay_ms(10); //10毫秒if(t==1000)				 t=0;if((t%20)==0)LED0=!LED0;myfree(SRAMIN,p);		//释放内存	}} 

三、运行与调试

请看录制好的视频演示。


四、总结

    总结:通过STM32单片机使用USB数据与电脑相连,不需要安装电脑驱动就可以用单片机控制电脑的鼠标,触摸屏和按键都可以同时控制鼠标的操作,程序设计精妙,拿来主义表现良好。这篇博文保留上述功能之外加入了无线遥杆控制和按键遥控,代码真的精简规范,非常适合二次开发和学习。这一篇的内容是接上一篇:《最简单DIY基于STM32的远程控制电脑系统①(电容触摸+按键控制)》,所以部分免费的资料请到上篇博文(第七篇)去下载。

    后期会推出体感遥控器的开源软硬件的方案,daodanjishui嵌入式核心技术值得期待。请认准我的品牌,不断更新和创新是我的特色。追求原创开源是我的宗旨。具体硬件和软件资料比较多,请读者打包下载才能快速掌握这套源码。

最后附上本博文代码下载地址
直接跳转

地址:https://www.cirmall.com/circuit/30880/


http://www.ppmy.cn/news/497891.html

相关文章

【SIGMOD 2023】深度学习弹性数据流水线系统GoldMiner,大幅提升任务和集群效率

第一板块&#xff1a;开篇 近日&#xff0c;阿里云机器学习平台PAI和北京大学杨智老师团队合作的论文《GoldMiner: Elastic Scaling of Training Data Pre-Processing Pipelines for Deep Learning》被数据库领域顶会SIGMOD 2023接收。 GoldMiner观察到深度学习任务中的数据预…

深入解析神经网络(Neural Networks)工作原理

目录 1. 神经网络的基本组成部分2. 神经元和激活函数3. 前向传播4. 反向传播5. 神经网络的层次结构6. 神经网络的应用7. 使用Python和TensorFlow库实现简单神经网络 神经网络&#xff08;Neural Networks&#xff09;是一种受到生物神经系统启发的人工智能模型&#xff0c;它在…

Makerbase CANable V2.0 固件升级或替换

第1部分 应用软件与固件 应用软件CANable V2.0CANable V1.0cangaroocandleLight/slcan(支持CAN FD)candleLight/slcan/cantactBUSMASTER V3.2.2candleLightcandleLight/pcan/cantactTSMastercandleLightcandleLight/pcan/cantactPCAN-Explorer 5、pcan view不支持pcancantacts…

【Python】数据库(创建库 访问 连接 创建表 编辑记录 案例:客户管理实现)

文章目录 * 库表与管理1.访问数据库1.1 连接与创建数据库1.2 创建表1.3 编辑表记录1.3.1 添加记录1.3.2 修改记录1.3.3 返回所有记录1.3.4 删除记录1.3.5 查询记录 1.4 案例&#xff1a;客户管理 SQLite 实现 * 库表与管理 1.访问数据库 SQLite 是 Python 自带的数据库管理模…

Web前端入门指南:必备知识与技能

&#x1f482; 个人网站:【海拥】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 目录 前言HTML基础CSS样式与…

做快乐的程序员 - 在淘宝网的一次讲座

原文地址为&#xff1a; 做快乐的程序员 - 在淘宝网的一次讲座 同学们&#xff1a; 我要讲的&#xff0c;是怎样做快乐的程序员。什么是快乐的程序员呢&#xff1f;就是把编程当作兴趣和爱好的人&#xff0c;享受着编程的快乐的一群人。 优秀的程序员都是从快乐的程序员开始…

#Geek Point# 创业、艺术家和量子物理

这张头图必须要专门发一下先。 是最近最喜欢的一个物件了。就这张小小的东西&#xff0c;我每天能拿出来看好多次。随意涂抹的浓墨重彩里透出爱心形状的天&#xff0c;爱因斯坦和卓别林&#xff0c;这两位人类史上最厉害的科学家和表演艺术家&#xff0c;共同站立着举着牌&…

缔造微软帝国的程序员保罗·艾伦因病离世

&#xff08;点击上方公众号&#xff0c;可快速关注&#xff09; 综合整理&#xff1a;程序员的那些事&#xff08;id: iProgrammer&#xff09; 参考&#xff1a;CNBC、伯乐在线、瘦陀、新浪科技、维基百科 10 月 16 日&#xff0c;据美国 CNBC 报道&#xff0c;微软联合创始人…