fms里c/s的一个例子

idPool = ["guest_1", "guest_2", "guest_3", "guest_4"];//数组,当堆栈用.全局的

application.onAppStart = function(){
   users_so = SharedObject.get("users");//获取本地共享对象users.注意,这是在服务端.不需要远程,而是本地
}

application.onConnect = function(client, name){//client为带协议的地址串的连接表示,name为输入的参数
   if (idPool.length <= 0){//如果对象池满
      application.rejectConnection(client, {msg:"Too many users."});//拒绝连接请求,给出信息,指明原因
   }
   client.id = idPool.pop();//从堆栈顶部弹出一个.并且给client多安个id属性。现在client有id属性了,后面可以使用了
   application.acceptConnection(client);//接受连接请求
   client.call("setID", null, client.id);//调用client的setID,给client发消息,将id传过去,null说明没有指定返回信息处理器
   users_so.setProperty(client.id, name); //将id:name值对保存到共享对象里。注意,这是服务器端
}

application.onDisconnect = function(client){
   idPool.push(client.id);//将要回收的id压回堆栈
   users_so.setProperty(client.id, null); //在共享对象里,将与id对应的值对设置为空,即删除。
}

myID = ""; //每个客户端都有一个id,表示自己,独一无二
nc = new NetConnection(); //连接对象。全局使用

/**
 * setID is a remote method that will be called by the server
 * after the client connects. Once we get our unique ID from the
 * server we can use it to publish our stream.
 */
nc.setID = function(id){ //setID方法,绑到连接上.如此,服务端就可以用client调用,给客户端发送消息了.这里,发送了id信息
    myID = id; //事实上,"我"的id是服务器分配的.
    statusInput.text = "Online. Your client's ID is: " + myID;//在状态栏显示在线信息及id
    ns = new NetStream(nc);//建立流
    ns.attachAudio(Microphone.get());//将流管道接到麦克音频源上
    var cam = Camera.get();//打开摄像头
    ns.attachVideo(cam);//将同一管道流接到摄像头上.这样,音频视频都接到同一管道上了.也可以使用上面接麦克的写法,一个
        //语句即可.因为下面还要用到,所以把引用拿出来了.
    ns.publish(id);//发布id信息
    _root[id].video.attachVideo(cam);//将摄像头同时连到自己的视频播放窗口.就能自拍了.同时有4个剪辑对象(被拖到)在舞台
        //上,形成数组.每个剪辑里有嵌入式视频与文本输入框.现在要访问剪辑里的视频对象,使用这种方式.video是剪辑里视频对象
    init();//开始初始化工作
}//这个方法在客户端执行,因此可以使用客户端的资源,如麦克和摄像头等.它被服务端调用,因此又可得到(传递)消息.

/**
 * onStatus is called whenever the status of the network
 * connection changes. It is how we know if we are connected
 * or not.
 */
nc.onStatus = function(info){//状态事件处理器.一旦网络连接状态改变,就调用它.诸如连接成功,失败等.info是服务器返回的
   connectButton.label = "Connect";
   connectButton.enabled = true;
   switch(info.code){
       case "NetConnection.Connect.Success":// 成功状态
          connectButton.label = "Disconnect";//标签改为"断开"
          statusInput.text = "Online";//标识"在线"
         
       break;
       case "NetConnection.Connect.Failed": //失败状态
          statusInput.text = "Cannot reach server. Possible network error.";
       break;
       case "NetConnection.Connect.Rejected"://连接拒绝
           statusInput.text = info.application.msg;//显示原因
       break;
       case "NetConnection.Connect.Closed"://连接关闭
           statusInput.text += " Connection closed.";
       break;
   }
}

connectButton.addEventListener("click", this);//给按钮注册事件监听器.this代表谁?
/**
 * click() is called when the connectButton is pressed.
 * Depending on the label of the button either a
 * connection is attempted or the current connection is
 * closed.
 */
function click(ev){//点击事件处理器.传入事件对象
    var button = ev.target;//取事件源
    var command = button.label;//取按钮的文字标签
    switch(command){
        case "Connect"://连接命令
           nc.connect("rtmp:/helloVideo", userNameInput.text);//连接,到服务端应用,传递用户名
           button.label = "Wait...";
           button.enabled = false;//按钮不可用
        break;
        case "Disconnect"://断开
           nc.close();//关闭连接
           button.label = "Connect";
        break;
    }
}

/**
 * init() is called after the server calls the setID method
 * It initializes the shared users object and then connects it.
 */
function init(){//服务端调用setID后,执行本初始化函数
    users_so = SharedObject.getRemote("users", nc.uri);//获取远程共享对象,到uri,连接到users上
    users_so.onSync = function(infoList){//共享对象同步事件处理器.共享对象里发生任何状态变化,都执行.信息列表里有具体信息
        for (var i in infoList){//逐条检测信息列表
            var info = infoList[i];//一条信息
            switch(info.code){//检测信息码
                case "change": //数据改变
                   var id = info.name;//取出名字,为id.name是信息的一个属性吗?规范在哪里?
                   var mc = _root[id];//找对应的剪辑对象
                   mc.nameInput.text = users_so.data[id];//还记得存入共享对象里的值对吗?现在按名字把值取出来.剪辑将它显示出来
                   if (myID != id){//判断数据变化的id与播放窗口是不是同一个。
                       var ns = new NetStream(nc);//建立管道流
                       mc.video.attachVideo(ns);//连到剪辑的播放窗口里
                       ns.play(id);//播放流, guest_1,
                       mc.ns = ns;//mc有ns属性吗?这里是新加的,还是已有的?在什么时候用到?还是已经用到了?
                   }//事实上,有4个窗口对象,只有一个是自己的,其余3个id都不一样.这样,就给3个窗口分别连到自己的流了.关键是
                        //每个窗口播放自己的流. 当然了,前提是数据流要变化.数据不变化,就不需要播放,因为没数据嘛
                break;
                case "delete"://有人离开了,就删除之
                   var id = info.name; //这个人离开了
                   var mc = _root[id];//取它的剪辑
                   mc.ns.close();//将剪辑里的流关闭.上面新加的属性,这里用上了
                   mc.nameInput.text = "";
                   mc.video.clear();//视频窗口处理
                break;
            }
        }//上面,info只有两个属性出现过:info.code和info.name.进一步查资料
    }
    users_so.connect(nc);    //共享对象连接. 注意:1)连接放在同步处理后面;2)有连接,就有状态变化,这都是服务端调用的
}
 
/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2025 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 "tim.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "stdio.h" #include "stm32f1xx_hal_tim.h" /* 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 */ uint32_t Diff = 0 ; uint8_t MeasureFlag = 0 ; uint8_t CapIndex = 0 ; uint32_t CapVal1 = 0 ; uint32_t CapVal2 = 0 ; float Period = 0; // 周期,单位us float Frequency = 0; // 频率,单位Hz /* 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 */ int fputc(int c,FILE * f) { uint8_t ch[1] ={c}; HAL_UART_Transmit (&huart1,ch,1,10); return c; } /* 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_TIM3_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ printf ("Timer Capture Function Test: \n"); HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if (MeasureFlag == 1) // 判断测量标志是否置位 { if (CapVal2 >= CapVal1) // 两次捕获在同一个计数周 { Diff = CapVal2 - CapVal1; } else // 两次捕获不在同一个计数 { Diff = ((0xFFFFFFFF + 1 - CapVal1) + CapVal2) ; } Period = (float)Diff * 13.8888889f; // 单位:ns Frequency = 72000000.0f / Diff; // 单位:Hz(正确公式) printf ("Period is: %.4fms\r\n",Period/10000.0); printf("Frequency is: %.2fHz\r\n", 100000000.0f / Diff); printf ("/***************************/\r\n"); MeasureFlag = 0; // 清除测量完成标志 HAL_Delay (1000); HAL_TIM_IC_Start_IT (&htim3, TIM_CHANNEL_2); // 启动下 } } /* 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_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; 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_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { printf("HAL_TIM_IC_CaptureCallback\n"); if( htim->Instance == TIM3 ) { if( htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2 ) { if(CapIndex == 0) { CapVal1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2); CapIndex = 1 ; } else if(CapIndex == 1) { CapVal2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2); HAL_TIM_IC_Stop_IT(htim, TIM_CHANNEL_2); CapIndex = 0; MeasureFlag = 1; } else { Error_Handler(); } } } } /* 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 */ 帮我看看为什么我的中断不触发
05-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值