单片机与WPF通信

  • 单片机使用联合体发送浮点数
union floatTypePosition
{
    struct xyValueStructure
    {
        float xValue;
        float yValue;
    }xyValueStruct;
    uint8_t para[8];
};//接下来只需给两个float数据赋值,相同位置偏移里的para数组则会存储float内存中的值;

//在发送数据的函数中写下面语句
union floatTypePosition FloatTypePosition;
FloatTypePosition.xyValueStruct.xValue = 100;
FloatTypePosition.xyValueStruct.yValue = 200;
HAL_UART_Transmit(&huart1,(uint8_t  *)FloatTypePosition.para,sizeof(FloatTypePosition.para),1000);
//强制类型转换
/*强制类型转化*/
发送数据函数:HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
uint8_t *pData:pData是 uint8_t 类型的指针,指针加1地址移动一个字节
int *pData:指针加1地址移动四个字节
所以对于 int para[10];串口发送其数据时需先将数组名强制类型转化为uint8_t型的指针;
或是直接:
uint8_t *p;
p = (uint8_t *)para;
HAL_UART_Transmit(..., p,....);
or
uint8_t sendbuff[10];
HAL_UART_Transmit(..., sendbuff,....);
//在实际使用中自己总喜欢避开使用指针,但确实方便,要积累下来

 

//注意此处,一开始这么写的,结构xValue与yValue实际存储值一样,测试时通过发现para的后四个元素值总变化发现错误的;
union floatTypePosition
{
        float xValue;
        float yValue;
       uint8_t para[8];
};
/*注意:因为在WPF中写的是一次读取一定长度的数据,一开始把数据头分开时接收总是错误,
然后合在一起发就没问题了,虽然感觉分开发也行,但是,,,,,,*/
    HAL_UART_Transmit(&huart1,(uint8_t *)sendDataHead[0],sizeof(sendDataHead[0]),1000);//这里不要拆开发,目前上位机接收是一次读的一段数据 
    HAL_UART_Transmit(&huart1,sendDataWpf,sizeof(sendDataWpf),1000);
    HAL_UART_Transmit(&huart1,(uint8_t *)sendDataHead[1],sizeof(sendDataHead[0]),1000);
  • WPF使用field Offset接收
        using System.Runtime.InteropServices;//需要额外引入的程序集

        public byte dataReceivedLengthCommended = 10;  //设定串口接收数据的长度,这样好一次读几个字节数据
        [StructLayout(LayoutKind.Explicit)]  //显示指定位置偏移必须的
        public struct union
        {
            [FieldOffset(0)] //值类型与引用类型不能同时用,数据头
            public byte temple0;

            [FieldOffset(1)]
            public byte temple1;
            [FieldOffset(2)]
            public byte temple2;
            [FieldOffset(3)]
            public byte temple3;
            [FieldOffset(4)]
            public byte temple4;

            [FieldOffset(5)]
            public byte temple5;
            [FieldOffset(6)]
            public byte temple6;
            [FieldOffset(7)]
            public byte temple7;
            [FieldOffset(8)]
            public byte temple8;

            [FieldOffset(9)]  //数据尾
            public byte temple9;

            [FieldOffset(1)]  //偏移量回归
            public float dataGpsLng;
            [FieldOffset(5)] 
            public float dataGpsLat;
        }
        public void portDataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                union reData = new union();
                /*一次读一个字节数据PORT.ReadByte(),当读到每一中数据对应的数据头后在相应的在读一定数目的数据,并还进行一下数据校验*/
                byte[] ReDatasTemp = new byte[dataReceivedLengthCommended];  //用于先存储一次发过来的数据,byte即是无符号整形
                Port.Read(ReDatasTemp, 0, ReDatasTemp.Length);
                if ((ReDatasTemp[0] == 0x65) && (ReDatasTemp[9] == 0x66)) 
                { 
                    reData.temple1 = ReDatasTemp[1];
                    reData.temple2 = ReDatasTemp[2];
                    reData.temple3 = ReDatasTemp[3];
                    reData.temple4 = ReDatasTemp[4];

                    reData.temple5 = ReDatasTemp[5];
                    reData.temple6 = ReDatasTemp[6];
                    reData.temple7 = ReDatasTemp[7];
                    reData.temple8 = ReDatasTemp[8];
                    //则浮点数就可以这么使用:reData.dataGpsLng,reData.dataGpsLat
                    receiveGPSDataDelagate = new ReceiveGPSDataDelagate(ChangeGPSText);                       
                    Dispatcher.Invoke(receiveGPSDataDelagate, reData.dataGpsLng, reData.dataGpsLat);                 }
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Beep.Play();
                MessageBox.Show(ex.Message, "error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
  • 单片机使用“原始的”串口发送
	 int16_t sendDataWpf[5] = {0x45,0x55,RemoteCh[0],RemoteCh[1],0x46}; //数据头和数据尾,左右油门
	 HAL_UART_Transmit(&huart1,(uint8_t *)sendDataWpf,sizeof(sendDataWpf),1000); //内存偏移量变为8
  • WPF使用字节合并接收
        public byte dataReceivedLengthCommended = 10;  
        public short[] speedYX = new short[2]; //油门数据;        
        public void portDataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                union reData = new union();
                byte[] ReDatasTemp = new byte[dataReceivedLengthCommended]; 
                Port.Read(ReDatasTemp, 0, ReDatasTemp.Length);
                if ( ((ReDatasTemp[0] | ((short)ReDatasTemp[1] << 8)) == 0x45)    
                    && ((ReDatasTemp[2] | ((short)ReDatasTemp[3] << 8)) == 0x55)
                    && ((ReDatasTemp[8] | ((short)ReDatasTemp[9] << 8)) == 0x46))  
                {
                    speedYX[0] = (short)(ReDatasTemp[4] | ((short)ReDatasTemp[5] << 8));  //不太清楚为什么要(short)
                    speedYX[1] = (short)(ReDatasTemp[6] | ((short)ReDatasTemp[7] << 8));
                    receiveSpeedDataDelagate = new ReceiveSpeedDataDelagate(ChangeSpeedYXText);    
                    Dispatcher.Invoke(receiveSpeedDataDelagate, speedYX[0], speedYX[1]);
                }
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Beep.Play();
                MessageBox.Show(ex.Message, "error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

Tips:这里不太清楚为什么移位后自动合并会变为int型,还需要自己转换回short 

/*注意此处通过使用移位合并数据的方式
单片机Hal_UART_Transmit(); 函数本身就是差分数据为一个字节一个字节的再发送数据,因此可以这样合并;
对于一个数据,不是byte长度会进行拆分,此数据先发其低字节,再发送其高字节,再发下一个数据的低字节、高字节;
注意合并时需先将要移位的数据进行强制类型转换,不然一移位,那个移位的数据低位自动补0数据就没了;
*/

Tips:在进行bool值的比较时 & 和 &&的效果一样的,但是后者更好,后者有短路的功能;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值