精华内容
下载资源
问答
  • 串口发送数据和接收数据,在此作一个简单的Demo.此Demo可以实现按下硬件按钮,灯亮,发送灯状态数据过来。...发送过去的数据:0代表1号灯亮,1代表1号灯灭、2代表2号灯亮,3代表2号灯灭、4代表3号灯亮,5代表3

    与串口发送数据和接收数据,在此作一个简单的Demo.此Demo可以实现按下硬件按钮,灯亮,发送灯状态数据过来。并且可以实现几个灯同时亮,发送灯的状态数据过来。PC端实现点击按钮让硬件灯亮。
    此处为4个灯,发送过来的数据:0代表暗,1代表亮。列如:1010代表1号灯和3号灯亮,2号和4号灯暗。
    发送过去的数据:0代表1号灯亮,1代表1号灯灭、2代表2号灯亮,3代表2号灯灭、4代表3号灯亮,5代表3号灯灭、6代表4号灯亮,7代表4号灯灭。
    布局代码:

    <Grid>
            <TextBox HorizontalAlignment="Left" Height="23" Margin="112,59,0,0" TextWrapping="Wrap" Name="txtSend" VerticalAlignment="Top" Width="120"/>
            <TextBox HorizontalAlignment="Left" Height="23" Margin="112,113,0,0" TextWrapping="Wrap" Name="txtReceive" VerticalAlignment="Top" Width="120"/>
            <Button Content="发送" Name="btnSend" HorizontalAlignment="Left" Margin="83,271,0,0" VerticalAlignment="Top" Width="35" Click="btnSend_Click"/>
            <Button Content="发送" Name="btnSend1" HorizontalAlignment="Left" Margin="143,271,0,0" VerticalAlignment="Top" Width="35" Click="btnSend1_Click"/>
            <Button Content="发送" Name="btnSend2" HorizontalAlignment="Left" Margin="203,271,0,0" VerticalAlignment="Top" Width="35" Click="btnSend2_Click"/>
            <Button Content="发送" Name="btnSend3" HorizontalAlignment="Left" Margin="263,271,0,0" VerticalAlignment="Top" Width="35" Click="btnSend3_Click"/>
    
    
            <Label Name="one" Background="Red" HorizontalAlignment="Left" Margin="84,190,0,0" VerticalAlignment="Top" Height="24" Width="28"/>
            <Label Name="two" Background="Red" HorizontalAlignment="Left" Margin="144,190,0,0" VerticalAlignment="Top" Height="24" Width="28"/>
            <Label Name="three" Background="Red" HorizontalAlignment="Left" Margin="204,190,0,0" VerticalAlignment="Top" Height="24" Width="28"/>
            <Label Name="four" Background="Red" HorizontalAlignment="Left" Margin="264,190,0,0" VerticalAlignment="Top" Height="24" Width="28"/>
    
    
    
        </Grid>

    后台代码:

    private SerialPort Sp = new SerialPort();
            public delegate void HandleInterfaceUpdataDelegate(string text);
            private HandleInterfaceUpdataDelegate interfaceUpdataHandle;
    
            String[] arr = { "0", "0", "0", "0" };//用于存储硬件上面灯状态

    其次在Loaded事件添加用于更改串口参数:

     //更改参数
                Sp.PortName = "COM3";
                Sp.BaudRate = 115200;
                Sp.Parity = Parity.None;
                Sp.StopBits = StopBits.One;
    编写监听和发送数据事件:
    private void Serial()
            {
                Sp.DataReceived += new SerialDataReceivedEventHandler(Sp_DataReceived);
                if (!Sp.IsOpen)
                {
                    Sp.Open();
                }
                //用字节的形式发送数据
                SendBytesData(Sp);
            }
    
            //发送二进制数据
            private void SendBytesData(SerialPort Sp)
            {
    
                byte[] bytesSend = System.Text.Encoding.Default.GetBytes(txtSend.Text);
                Sp.Write(bytesSend, 0, bytesSend.Length);
    
            }
    
    
    
            public void Sp_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
            {
               /* byte[] readBuffer = new byte[Sp.ReadBufferSize];
                Sp.Read(readBuffer, 0, readBuffer.Length);
                //Dispatcher.Invoke(interfaceUpdataHandle, new string[]{ Encoding.UTF8.GetString(readBuffer)});
                Dispatcher.Invoke(interfaceUpdataHandle, new string[] { Encoding.ASCII.GetString(readBuffer) });
                //Dispatcher.Invoke(interfaceUpdateHandle, new string[] { Encoding.ASCII.GetString(buf) });*/
    
                SerialPort serialPort = (SerialPort)(sender);
                System.Threading.Thread.Sleep(100);//延缓一会,用于防止硬件发送速率跟不上缓存数据导致的缓存数据杂乱
                int n = serialPort.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致  
                byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据  
                //received_count += n;//增加接收计数  
                serialPort.Read(buf, 0, n);//读取缓冲数据  
                //因为要访问ui资源,所以需要使用invoke方式同步ui
                interfaceUpdataHandle = new HandleInterfaceUpdataDelegate(UpdateTextBox);//实例化委托对象
                // Dispatcher.Invoke(interfaceUpdateHandle, new string[] { Encoding.ASCII.GetString(buf) });
                Dispatcher.Invoke(interfaceUpdataHandle, new string[] { Encoding.ASCII.GetString(buf) });
    
                //serialPort.Close();
    
    
    
    
            }
    
            private void UpdateTextBox(string text)
            {
                txtReceive.Text = text;
    
                String Receive = Convert.ToString(text);
                if (Receive != "")
                {
                    // MessageBox.Show("receive", Receive);
                    String Receive1 = Receive.Substring(0, 1);
                    String Receive2 = Receive.Substring(1, 1);
                    String Receive3 = Receive.Substring(2, 1);
                    String Receive4 = Receive.Substring(3, 1);
                    if (Receive1 == 1.ToString())
                    {
                        one.Background = new SolidColorBrush(Colors.MediumAquamarine);
                        arr[0] = 1.ToString();
                    }
                    else
                    {
                        one.Background = new SolidColorBrush(Colors.Red);
                        arr[0] = 0.ToString();
                    }
                    if (Receive2 == 1.ToString())
                    {
                        two.Background = new SolidColorBrush(Colors.MediumAquamarine);
                        arr[1] = 1.ToString();
                    }
                    else
                    {
                        two.Background = new SolidColorBrush(Colors.Red);
                        arr[1] = 0.ToString();
                    }
                    if (Receive3 == 1.ToString())
                    {
                        three.Background = new SolidColorBrush(Colors.MediumAquamarine);
                        arr[2] = 1.ToString();
                    }
                    else
                    {
                        three.Background = new SolidColorBrush(Colors.Red);
                        arr[2] = 0.ToString();
                    }
                    if (Receive4 == 1.ToString())
                    {
                        four.Background = new SolidColorBrush(Colors.MediumAquamarine);
                        arr[3] = 1.ToString();
                    }
                    else
                    {
                        four.Background = new SolidColorBrush(Colors.Red);
                        arr[3] = 0.ToString();
                    }
                    //String abc = Convert.ToString(arr);
                    //MessageBox.Show("abc", abc);
    
                    // MessageBox.Show("arr", arr);
                }
            }

    最后button点击事件添加:

     private void btnSend_Click(object sender, RoutedEventArgs e)
            {
                if (arr[0] == 0.ToString())
                {
                    txtSend.Text = "0";               
                    Serial();
                }
                else
                {
                    txtSend.Text = "1";
                    Serial();
                }
            }
    
            private void btnSend1_Click(object sender, RoutedEventArgs e)
            {
                if (arr[1] == 0.ToString())
                {
                    txtSend.Text = "2";
                    Serial();
                }
                else
                {
                    txtSend.Text = "3";
                    Serial();
                }
            }
    
            private void btnSend2_Click(object sender, RoutedEventArgs e)
            {
                if (arr[2] == 0.ToString())
                {
                    txtSend.Text = "4";
                    Serial();
                }
                else
                {
                    txtSend.Text = "5";
                    Serial();
    
                }
            }
    
            private void btnSend3_Click(object sender, RoutedEventArgs e)
            {
                if (arr[3] == 0.ToString())
                {
                    txtSend.Text = "6";
                    Serial();
                }
                else
                {
                    txtSend.Text = "7";
                    Serial();
                }
            }

    要想在程序开始时就可以监听数据,在其Loaded里面添加上: Serial();
    完整后台代码:

     public partial class MainWindow : Window
        {
    
            private SerialPort Sp = new SerialPort();
            public delegate void HandleInterfaceUpdataDelegate(string text);
            private HandleInterfaceUpdataDelegate interfaceUpdataHandle;
    
            String[] arr = { "0", "0", "0", "0" };//用于存储硬件上面灯状态
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                //更改参数
                Sp.PortName = "COM3";
                Sp.BaudRate = 115200;
                Sp.Parity = Parity.None;
                Sp.StopBits = StopBits.One;
    
                Serial();
            }
    
            private void btnSend_Click(object sender, RoutedEventArgs e)
            {
                if (arr[0] == 0.ToString())
                {
                    txtSend.Text = "0";               
                    Serial();
                }
                else
                {
                    txtSend.Text = "1";
                    Serial();
                }
            }
    
            private void btnSend1_Click(object sender, RoutedEventArgs e)
            {
                if (arr[1] == 0.ToString())
                {
                    txtSend.Text = "2";
                    Serial();
                }
                else
                {
                    txtSend.Text = "3";
                    Serial();
                }
            }
    
            private void btnSend2_Click(object sender, RoutedEventArgs e)
            {
                if (arr[2] == 0.ToString())
                {
                    txtSend.Text = "4";
                    Serial();
                }
                else
                {
                    txtSend.Text = "5";
                    Serial();
    
                }
            }
    
            private void btnSend3_Click(object sender, RoutedEventArgs e)
            {
                if (arr[3] == 0.ToString())
                {
                    txtSend.Text = "6";
                    Serial();
                }
                else
                {
                    txtSend.Text = "7";
                    Serial();
                }
            }
    
            private void Serial()
            {
                Sp.DataReceived += new SerialDataReceivedEventHandler(Sp_DataReceived);
                if (!Sp.IsOpen)
                {
                    Sp.Open();
                }
                //用字节的形式发送数据
                SendBytesData(Sp);
            }
    
            //发送二进制数据
            private void SendBytesData(SerialPort Sp)
            {
    
                byte[] bytesSend = System.Text.Encoding.Default.GetBytes(txtSend.Text);
                Sp.Write(bytesSend, 0, bytesSend.Length);
    
            }
    
    
    
            public void Sp_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
            {
               /* byte[] readBuffer = new byte[Sp.ReadBufferSize];
                Sp.Read(readBuffer, 0, readBuffer.Length);
                //Dispatcher.Invoke(interfaceUpdataHandle, new string[]{ Encoding.UTF8.GetString(readBuffer)});
                Dispatcher.Invoke(interfaceUpdataHandle, new string[] { Encoding.ASCII.GetString(readBuffer) });
                //Dispatcher.Invoke(interfaceUpdateHandle, new string[] { Encoding.ASCII.GetString(buf) });*/
    
                SerialPort serialPort = (SerialPort)(sender);
                System.Threading.Thread.Sleep(100);//延缓一会,用于防止硬件发送速率跟不上缓存数据导致的缓存数据杂乱
                int n = serialPort.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致  
                byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据  
                //received_count += n;//增加接收计数  
                serialPort.Read(buf, 0, n);//读取缓冲数据  
                //因为要访问ui资源,所以需要使用invoke方式同步ui
                interfaceUpdataHandle = new HandleInterfaceUpdataDelegate(UpdateTextBox);//实例化委托对象
                // Dispatcher.Invoke(interfaceUpdateHandle, new string[] { Encoding.ASCII.GetString(buf) });
                Dispatcher.Invoke(interfaceUpdataHandle, new string[] { Encoding.ASCII.GetString(buf) });
    
                //serialPort.Close();
    
    
    
    
            }
    
            private void UpdateTextBox(string text)
            {
                txtReceive.Text = text;
    
                String Receive = Convert.ToString(text);
                if (Receive != "")
                {
                    // MessageBox.Show("receive", Receive);
                    String Receive1 = Receive.Substring(0, 1);
                    String Receive2 = Receive.Substring(1, 1);
                    String Receive3 = Receive.Substring(2, 1);
                    String Receive4 = Receive.Substring(3, 1);
                    if (Receive1 == 1.ToString())
                    {
                        one.Background = new SolidColorBrush(Colors.MediumAquamarine);
                        arr[0] = 1.ToString();
                    }
                    else
                    {
                        one.Background = new SolidColorBrush(Colors.Red);
                        arr[0] = 0.ToString();
                    }
                    if (Receive2 == 1.ToString())
                    {
                        two.Background = new SolidColorBrush(Colors.MediumAquamarine);
                        arr[1] = 1.ToString();
                    }
                    else
                    {
                        two.Background = new SolidColorBrush(Colors.Red);
                        arr[1] = 0.ToString();
                    }
                    if (Receive3 == 1.ToString())
                    {
                        three.Background = new SolidColorBrush(Colors.MediumAquamarine);
                        arr[2] = 1.ToString();
                    }
                    else
                    {
                        three.Background = new SolidColorBrush(Colors.Red);
                        arr[2] = 0.ToString();
                    }
                    if (Receive4 == 1.ToString())
                    {
                        four.Background = new SolidColorBrush(Colors.MediumAquamarine);
                        arr[3] = 1.ToString();
                    }
                    else
                    {
                        four.Background = new SolidColorBrush(Colors.Red);
                        arr[3] = 0.ToString();
                    }
                    //String abc = Convert.ToString(arr);
                    //MessageBox.Show("abc", abc);
    
                    // MessageBox.Show("arr", arr);
                }
            }
    
    
        }

    这样可以实现btn和硬件本身按钮同时控制灯亮灯灭。
    若转载请注明转载处。

    展开全文
  • 1 基础知识点DMADMA(Direct Memory ...STM32F4的DMA通道选择如下:接下来的程序思路如下:2 编程要点2.1 DMA发送2.1.1 串口DMA发送配置由于是发送不定长的数据,先不需要配置发送的长度,在每次的发送时,再配置。/...

    578f85ea47c72b9316822fb578385358.png

    1 基础知识点

    DMA

    DMA(Direct Memory Access),即直接内存存储,在一些数据的传输中,如串口、SPI等,采用DMA方式,传输过程不需要CPU参与,可用让CPU有更多的时间处理其他的事情。

    STM32F4的DMA通道选择如下:

    237feee5d5f5bfc9bf57e8dc66528ef2.png

    接下来的程序思路如下:

    d71a17135444a05eacf090391cbc8b58.png

    2 编程要点

    2.1 DMA发送

    2.1.1 串口DMA发送配置

    由于是发送不定长的数据,先不需要配置发送的长度,在每次的发送时,再配置。

    //=======================================
    //串口DMA发送配置
    //=======================================
    void dma_uart_tx_init()
    {
        DMA_InitTypeDef  DMA_InitStructure;
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能 
    
        DMA_DeInit(Uart_Tx_DMAStream);//使用----->DMA2_Stream7
        while (DMA_GetCmdStatus(Uart_Tx_DMAStream) != DISABLE){}//等待DMA可配置 
    
        /* 配置 DMA Stream */
        DMA_InitStructure.DMA_Channel            = DMA_Channel_4;              //通道选择
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;           //目的:DMA外设地址
        DMA_InitStructure.DMA_Memory0BaseAddr    = (u32)SendBuff;              //源:DMA存储器0地址
        DMA_InitStructure.DMA_DIR                = DMA_DIR_MemoryToPeripheral; //方向:存储器到外设模式
        //DMA_InitStructure.DMA_BufferSize       = BUF_SIZE;                   //长度:数据传输量(先不配置)
        DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;  //外设非增量模式
        DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;       //存储器增量模式
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
        DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;    //存储器数据长度:8位
        DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;            //使用普通模式 
        DMA_InitStructure.DMA_Priority           = DMA_Priority_Medium;        //DMA优先级:中等优先级
        DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Disable;       //FIFO模式 
        DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_Full;     //FIFO大小
        DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;     //存储器单次传输
        DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single; //外设单次传输
        DMA_Init(Uart_Tx_DMAStream, &DMA_InitStructure);//初始化DMA Stream
    
        //中断配置
        DMA_ITConfig(Uart_Tx_DMAStream,DMA_IT_TC,ENABLE);  //配置DMA发送完成后产生中断
        NVIC_InitTypeDef NVIC_InitStructure;
        NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream7_IRQn;//
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=7;//抢占优先级8
        NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;       //子优先级0
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         //IRQ通道使能
        NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
    
        USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);  //使能串口1的DMA发送
        DMA_Cmd (Uart_Tx_DMAStream,DISABLE);//先不要使能DMA!           
    }

    2.1.2 DMA发送完成中断

    DMA发送完成后,触发DMA发送完成中断,这里可用释放自定义的DMA发送完成信号量,表明下次的DMA传输可用进行。

    //=======================================
    //DMA发送完成中断服务程序
    //=======================================
    void DMA2_Stream7_IRQHandler(void)
    {
        BaseType_t xHigherPriorityTaskWoken;
        //printf("ooooooorn");
        if(DMA_GetITStatus(Uart_Tx_DMAStream,DMA_IT_TCIF7)!= RESET) //检查DMA传输完成中断 DMA_IT_TCIF7
        {
            DMA_ClearITPendingBit(Uart_Tx_DMAStream,DMA_IT_TCIF7); 
            //printf("dma tx okrn");
            if(uartDMATCSemaphore!=NULL)
            {
                //释放二值信号量
                xSemaphoreGiveFromISR(uartDMATCSemaphore,&xHigherPriorityTaskWoken);    //释放DMA传输完成二值信号量
            }
            portYIELD_FROM_ISR(xHigherPriorityTaskWoken);//如果需要的话进行一次任务切换
        }
    }

    2.1.3 DMA发送函数接口

    //=======================================
    //串口DMA发送函数
    //======================================= 
    void uart_DMA_send(u8 *str,u16 ndtr)
    {
        u8 i;
        u8 *p=str;
    
        while(xSemaphoreTake(uartDMATCSemaphore,2)!=pdTRUE);//获取信号量,等待DMA发送可用
    
        DMA_Cmd(Uart_Tx_DMAStream, DISABLE);                      //关闭DMA传输 
        while (DMA_GetCmdStatus(Uart_Tx_DMAStream) != DISABLE){}    //确保DMA可以被设置  
        DMA_SetCurrDataCounter(Uart_Tx_DMAStream,ndtr);          //数据传输量 
        for(i=0;i<ndtr;i++)
        {
            SendBuff[i]=*p++;
        }
        DMA_Cmd(Uart_Tx_DMAStream, ENABLE);                      //开启DMA传输 
    }

    2.2 DMA接收

    2.2.1 串口DMA接收配置

    需要配置一个接收地址和一个接收长度,用于DMA接收数据的暂存。

    //=======================================
    //串口DMA接收配置
    //=======================================
    void dma_uart_rx_init()
    {
        DMA_InitTypeDef  DMA_InitStructure;
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能 
    
        DMA_DeInit(Uart_Rx_DMAStream);//使用----->DMA2_Stream5
        while (DMA_GetCmdStatus(Uart_Rx_DMAStream) != DISABLE){}//等待DMA可配置 
    
        /* 配置 DMA Stream */
        DMA_InitStructure.DMA_Channel            = DMA_Channel_4;              //通道选择
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;           //源:DMA外设地址
        DMA_InitStructure.DMA_Memory0BaseAddr    = (u32)ReceiveBuff;           //目的:DMA存储器0地址
        DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralToMemory; //方向:外设到存储器模式
        DMA_InitStructure.DMA_BufferSize         = BUF_SIZE;                   //长度:数据传输量
        DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;  //外设非增量模式
        DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;       //存储器增量模式
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
        DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;    //存储器数据长度:8位
        DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;            //使用普通模式 
        DMA_InitStructure.DMA_Priority           = DMA_Priority_Medium;        //DMA优先级:中等优先级
        DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Disable;       //FIFO模式 
        DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_Full;     //FIFO大小
        DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;     //存储器单次传输
        DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single; //外设单次传输
        DMA_Init(Uart_Rx_DMAStream, &DMA_InitStructure);//初始化DMA Stream
    
        USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);  //使能串口1的DMA接收
        DMA_Cmd (Uart_Rx_DMAStream,ENABLE);//使能          
    }

    2.2.2 串口空闲中断

    串口空闲中断的作用与上一篇

    码农爱学习:FreeRTOS例程3-串口中断接收不定长的数据与二值信号量的使用zhuanlan.zhihu.com
    ec44cb92e7bcef576d165460c4aec2b4.png

    介绍的一样,都是在发送完一串字符后被触发,这次由于使用了DMA接收,所以接收的数据在DMA缓冲区,且接收的数据长度可用根DMA接收通道的总长度与剩余长度的差值来计算,将接收的数据复制出来使用即可,同时释放自定义的串口空闲信号量,以便其它任务可用及时获取串口接收到的数据。

    //=======================================
    //串口1空闲中断服务程序,用于DMA接收
    //=======================================
    void USART1_IRQHandler(void)                    
    {
        uint8_t data;//接收数据暂存变量
        BaseType_t xHigherPriorityTaskWoken;
    
        if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)//空闲中断
        {
            data = USART1->SR;
            data = USART1->DR;
    
            DMA_Cmd(Uart_Rx_DMAStream,DISABLE);//关闭DMA接收
            while (DMA_GetCmdStatus(Uart_Rx_DMAStream) != DISABLE){}    //确保DMA可以被设置 
            rx_cnt = BUF_SIZE - DMA_GetCurrDataCounter(Uart_Rx_DMAStream);//得到真正接收数据个数  
            DMA_SetCurrDataCounter(Uart_Rx_DMAStream,BUF_SIZE);//重新设置接收数据个数    
            //printf("rx_cnt:%drn",rx_cnt);
            memcpy(rxbuf,ReceiveBuff,rx_cnt);//先复制出来,防止下次的数据来了之后将其覆盖
            DMA_ClearFlag(Uart_Rx_DMAStream,DMA_FLAG_TCIF5 | DMA_FLAG_FEIF5 | DMA_FLAG_DMEIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5);//这里的各种标志还没搞懂
            DMA_Cmd(Uart_Rx_DMAStream,ENABLE); //开启DMA接收
    
            if(uartRxIDLESemaphore!=NULL)
            {
                //printf("nnnnnnnrn");
                //释放二值信号量
                xSemaphoreGiveFromISR(uartRxIDLESemaphore,&xHigherPriorityTaskWoken);//释放串口空闲中断二值信号量
            }
            portYIELD_FROM_ISR(xHigherPriorityTaskWoken);//如果需要的话进行一次任务切换
        }
    }

    2.3 串口配置与测试任务

    2.3.1 串口配置

    基础的GPIO配置,以及串口空闲中断配置,并调用上面的串口DMA发送与接收配置。

    //=======================================
    //串口配置
    //=======================================
    void uart_init(u32 bound)
    {
        //GPIO端口设置
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
    
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
    
        //串口1对应引脚复用映射
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1
    
        //USART1端口配置
        GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;             //复用功能
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         //速度50MHz
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;            //推挽复用输出
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;             //上拉
        GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10
    
        //USART1 初始化设置
        USART_InitStructure.USART_BaudRate            = bound;                         //波特率设置
        USART_InitStructure.USART_WordLength          = USART_WordLength_8b;           //字长为8位数据格式
        USART_InitStructure.USART_StopBits            = USART_StopBits_1;              //一个停止位
        USART_InitStructure.USART_Parity              = USART_Parity_No;               //无奇偶校验位
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
        USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx; //收发模式
        USART_Init(USART1, &USART_InitStructure); //初始化串口1
    
        //DMA Config
        dma_uart_tx_init();//串口DMA发送配置
        dma_uart_rx_init();//串口DMA接收配置
    
        USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口空闲中断
        //Usart1 NVIC 配置
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;       //串口1中断通道
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=6; //抢占优先级8
        NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;       //子优先级0
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         //IRQ通道使能
        NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
    
        USART_Cmd(USART1, ENABLE);  //使能串口1 
    }

    2.3.2 测试任务

    创建DMA发送完成信号量和串口空闲信号量,并先释放DMA发送完成信号量,用于第一次DMA发送时获取信号量。然后测试两条DMA发送不定长字符串,最后测试DMA接收不定长字符串。

    //打印任务函数(测试任务)
    void print_task(void *pvParameters)
    {
        //创建二值信号量
        uartDMATCSemaphore = xSemaphoreCreateBinary();
        uartRxIDLESemaphore = xSemaphoreCreateBinary();
        xSemaphoreGive(uartDMATCSemaphore);
    
        u8 str1[]="ma nong ai xue xirn";
        uart_DMA_send(str1,sizeof(str1));
    
        u8 str2[]="xxpcb.github.iorn";
        uart_DMA_send(str2,sizeof(str2));
    
        BaseType_t err = pdFALSE;
        while(1)
        {
            err=xSemaphoreTake(uartRxIDLESemaphore,5);  //获取信号量
            if(err==pdTRUE)                         //获取信号量成功
            {  
                uart_DMA_send("receive:",sizeof("receive:"));
                uart_DMA_send(rxbuf,rx_cnt);
                uart_DMA_send("rn",sizeof("rn"));
    
                rx_cnt=0;
            }
        }
    }

    3 实验结果

    通过串口助手,可以先接收到DMA发送的两个字符串(第一条hello是测试串口的,不是DMA发的),然后通过串口调试助手发送两次nice to meet you,测试DMA接收。

    hello
    ma nong ai xue xi
    xxpcb.github.io
    receive:nice to meet you
    receive:nice to meet you

    完整工程代码已保存至GitHub:

    https://github.com/xxpcb/FreeRTOS-STM32F407-examplesgithub.com

    觉得文章有用,可以关注我哟~

    展开全文
  • 1基础知识点DMADMA(Direct Memory Access...STM32F4的DMA通道选择如下:接下来的程序思路如下:2编程要点2.1DMA发送2.1.1串口DMA发送配置由于是发送不定长的数据,先不需要配置发送的长度,在每次的发送时,再配置。...

    1基础知识点

    DMA

    DMA(Direct Memory Access),即直接内存存储,在一些数据的传输中,如串口、SPI等,采用DMA方式,传输过程不需要CPU参与,可用让CPU有更多的时间处理其他的事情。

    STM32F4的DMA通道选择如下:

    06bda72cf6ed2318f004dc6e96db4ab7.png

    接下来的程序思路如下:

    9060d7219678e68b955cb8fdf432aa7a.png

    2编程要点

    2.1DMA发送

    2.1.1串口DMA发送配置

    由于是发送不定长的数据,先不需要配置发送的长度,在每次的发送时,再配置。

    //=======================================//串口DMA发送配置//=======================================void dma_uart_tx_init(){    DMA_InitTypeDef  DMA_InitStructure;    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能    DMA_DeInit(Uart_Tx_DMAStream);//使用----->DMA2_Stream7    while (DMA_GetCmdStatus(Uart_Tx_DMAStream) != DISABLE){}//等待DMA可配置    /* 配置 DMA Stream */    DMA_InitStructure.DMA_Channel            = DMA_Channel_4;              //通道选择    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;           //目的:DMA外设地址    DMA_InitStructure.DMA_Memory0BaseAddr    = (u32)SendBuff;              //源:DMA存储器0地址    DMA_InitStructure.DMA_DIR                = DMA_DIR_MemoryToPeripheral; //方向:存储器到外设模式    //DMA_InitStructure.DMA_BufferSize       = BUF_SIZE;                   //长度:数据传输量(先不配置)    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;  //外设非增量模式    DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;       //存储器增量模式    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位    DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;    //存储器数据长度:8位    DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;            //使用普通模式    DMA_InitStructure.DMA_Priority           = DMA_Priority_Medium;        //DMA优先级:中等优先级    DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Disable;       //FIFO模式    DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_Full;     //FIFO大小    DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;     //存储器单次传输    DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single; //外设单次传输    DMA_Init(Uart_Tx_DMAStream, &DMA_InitStructure);//初始化DMA Stream    //中断配置    DMA_ITConfig(Uart_Tx_DMAStream,DMA_IT_TC,ENABLE);  //配置DMA发送完成后产生中断    NVIC_InitTypeDef NVIC_InitStructure;    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream7_IRQn;//    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=7;//抢占优先级8    NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;       //子优先级0    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         //IRQ通道使能    NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器    USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);  //使能串口1的DMA发送    DMA_Cmd (Uart_Tx_DMAStream,DISABLE);//先不要使能DMA!}

    2.1.2DMA发送完成中断

    DMA发送完成后,触发DMA发送完成中断,这里可用释放自定义的DMA发送完成信号量,表明下次的DMA传输可用进行。

    //=======================================//DMA发送完成中断服务程序//=======================================void DMA2_Stream7_IRQHandler(void){    BaseType_t xHigherPriorityTaskWoken;    //printf("ooooooo\r\n");    if(DMA_GetITStatus(Uart_Tx_DMAStream,DMA_IT_TCIF7)!= RESET) //检查DMA传输完成中断 DMA_IT_TCIF7    {        DMA_ClearITPendingBit(Uart_Tx_DMAStream,DMA_IT_TCIF7);        //printf("dma tx ok\r\n");        if(uartDMATCSemaphore!=NULL)        {            //释放二值信号量            xSemaphoreGiveFromISR(uartDMATCSemaphore,&xHigherPriorityTaskWoken);    //释放DMA传输完成二值信号量        }        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);//如果需要的话进行一次任务切换    }}

    2.1.3DMA发送函数接口

    //=======================================//串口DMA发送函数//=======================================void uart_DMA_send(u8 *str,u16 ndtr){    u8 i;    u8 *p=str;    while(xSemaphoreTake(uartDMATCSemaphore,2)!=pdTRUE);//获取信号量,等待DMA发送可用    DMA_Cmd(Uart_Tx_DMAStream, DISABLE);                      //关闭DMA传输    while (DMA_GetCmdStatus(Uart_Tx_DMAStream) != DISABLE){}    //确保DMA可以被设置      DMA_SetCurrDataCounter(Uart_Tx_DMAStream,ndtr);          //数据传输量    for(i=0;i{        SendBuff[i]=*p++;}    DMA_Cmd(Uart_Tx_DMAStream, ENABLE);                      //开启DMA传输}

    2.2DMA接收

    2.2.1串口DMA接收配置

    需要配置一个接收地址和一个接收长度,用于DMA接收数据的暂存。

    //=======================================//串口DMA接收配置//=======================================void dma_uart_rx_init(){    DMA_InitTypeDef  DMA_InitStructure;    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能    DMA_DeInit(Uart_Rx_DMAStream);//使用----->DMA2_Stream5    while (DMA_GetCmdStatus(Uart_Rx_DMAStream) != DISABLE){}//等待DMA可配置    /* 配置 DMA Stream */    DMA_InitStructure.DMA_Channel            = DMA_Channel_4;              //通道选择    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;           //源:DMA外设地址    DMA_InitStructure.DMA_Memory0BaseAddr    = (u32)ReceiveBuff;           //目的:DMA存储器0地址    DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralToMemory; //方向:外设到存储器模式    DMA_InitStructure.DMA_BufferSize         = BUF_SIZE;                   //长度:数据传输量    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;  //外设非增量模式    DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;       //存储器增量模式    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位    DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;    //存储器数据长度:8位    DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;            //使用普通模式    DMA_InitStructure.DMA_Priority           = DMA_Priority_Medium;        //DMA优先级:中等优先级    DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Disable;       //FIFO模式    DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_Full;     //FIFO大小    DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;     //存储器单次传输    DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single; //外设单次传输    DMA_Init(Uart_Rx_DMAStream, &DMA_InitStructure);//初始化DMA Stream    USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);  //使能串口1的DMA接收    DMA_Cmd (Uart_Rx_DMAStream,ENABLE);//使能          }

    2.2.2串口空闲中断

    串口空闲中断的作用与上一篇FreeRTOS例程3-串口中断接收不定长的数据与二值信号量的使用介绍的一样,都是在发送完一串字符后被触发,这次由于使用了DMA接收,所以接收的数据在DMA缓冲区,且接收的数据长度可用根DMA接收通道的总长度与剩余长度的差值来计算,将接收的数据复制出来使用即可,同时释放自定义的串口空闲信号量,以便其它任务可用及时获取串口接收到的数据。

    //=======================================//串口1空闲中断服务程序,用于DMA接收//=======================================void USART1_IRQHandler(void)                    {    uint8_t data;//接收数据暂存变量    BaseType_t xHigherPriorityTaskWoken;    if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)//空闲中断{        data = USART1->SR;        data = USART1->DR;        DMA_Cmd(Uart_Rx_DMAStream,DISABLE);//关闭DMA接收        while (DMA_GetCmdStatus(Uart_Rx_DMAStream) != DISABLE){}    //确保DMA可以被设置        rx_cnt = BUF_SIZE - DMA_GetCurrDataCounter(Uart_Rx_DMAStream);//得到真正接收数据个数          DMA_SetCurrDataCounter(Uart_Rx_DMAStream,BUF_SIZE);//重新设置接收数据个数            //printf("rx_cnt:%d\r\n",rx_cnt);        memcpy(rxbuf,ReceiveBuff,rx_cnt);//先复制出来,防止下次的数据来了之后将其覆盖        DMA_ClearFlag(Uart_Rx_DMAStream,DMA_FLAG_TCIF5 | DMA_FLAG_FEIF5 | DMA_FLAG_DMEIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5);//这里的各种标志还没搞懂        DMA_Cmd(Uart_Rx_DMAStream,ENABLE); //开启DMA接收        if(uartRxIDLESemaphore!=NULL)        {            //printf("nnnnnnn\r\n");            //释放二值信号量            xSemaphoreGiveFromISR(uartRxIDLESemaphore,&xHigherPriorityTaskWoken);//释放串口空闲中断二值信号量        }        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);//如果需要的话进行一次任务切换}}

    2.3串口配置与测试任务

    2.3.1串口配置

    基础的GPIO配置,以及串口空闲中断配置,并调用上面的串口DMA发送与接收配置。

    //=======================================//串口配置//=======================================void uart_init(u32 bound){    //GPIO端口设置    GPIO_InitTypeDef GPIO_InitStructure;    USART_InitTypeDef USART_InitStructure;    NVIC_InitTypeDef NVIC_InitStructure;    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟    //串口1对应引脚复用映射    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1    //USART1端口配置    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;             //复用功能    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         //速度50MHz    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;            //推挽复用输出    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;             //上拉    GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10    //USART1 初始化设置    USART_InitStructure.USART_BaudRate            = bound;                         //波特率设置    USART_InitStructure.USART_WordLength          = USART_WordLength_8b;           //字长为8位数据格式    USART_InitStructure.USART_StopBits            = USART_StopBits_1;              //一个停止位    USART_InitStructure.USART_Parity              = USART_Parity_No;               //无奇偶校验位    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制    USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx; //收发模式    USART_Init(USART1, &USART_InitStructure); //初始化串口1    //DMA Config    dma_uart_tx_init();//串口DMA发送配置    dma_uart_rx_init();//串口DMA接收配置    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口空闲中断    //Usart1 NVIC 配置    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;       //串口1中断通道    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=6; //抢占优先级8    NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;       //子优先级0    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         //IRQ通道使能    NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器    USART_Cmd(USART1, ENABLE);  //使能串口1}

    2.3.2测试任务

    创建DMA发送完成信号量和串口空闲信号量,并先释放DMA发送完成信号量,用于第一次DMA发送时获取信号量。然后测试两条DMA发送不定长字符串,最后测试DMA接收不定长字符串。

    //打印任务函数(测试任务)void print_task(void *pvParameters){    //创建二值信号量    uartDMATCSemaphore = xSemaphoreCreateBinary();    uartRxIDLESemaphore = xSemaphoreCreateBinary();    xSemaphoreGive(uartDMATCSemaphore);    u8 str1[]="ma nong ai xue xi\r\n";    uart_DMA_send(str1,sizeof(str1));    u8 str2[]="xxpcb.github.io\r\n";    uart_DMA_send(str2,sizeof(str2));    BaseType_t err = pdFALSE;    while(1)    {        err=xSemaphoreTake(uartRxIDLESemaphore,5);  //获取信号量        if(err==pdTRUE)                         //获取信号量成功        {              uart_DMA_send("receive:",sizeof("receive:"));            uart_DMA_send(rxbuf,rx_cnt);            uart_DMA_send("\r\n",sizeof("\r\n"));            rx_cnt=0;        }    }}

    3实验结果

    通过串口助手,可以先接收到DMA发送的两个字符串(第一条hello是测试串口的,不是DMA发的),然后通过串口调试助手发送两次nice to meet you,测试DMA接收。

    helloma nong ai xue xixxpcb.github.ioreceive:nice to meet youreceive:nice to meet you

    完整工程代码已保存至GitHub:https://github.com/xxpcb/FreeRTOS-STM32F407-examples

    展开全文
  • 在keil5在编程环境下,想要实现功能是:利用中断,让串口接收数据,串口一发送数据 部分代码如下: int main(void) { //初始化USART1和UART4 配置模式为 115200 8-N-1,通过USART1发送数据,通过UART4接收...
  • 1.如果想把接收的结果显示的更多列,以方便查看接收的结果,可以双击接收文本框, 接收结果文本框就会显示的更宽,再次双击,就会恢复原状。 2.可以16进制和ASC码混合发送,具体输入方法可以鼠标停在相应控件上...
  • 串口2发送数据控制led灯亮灭,串口2发送定时时间led定时亮灭 如果串口2发送“led on”打开 “ledoff”关闭 “set12231234”表示定时功能,12点23分打开,到达12点34分自动关闭 “anolek”"anoledg...
  • 下位机有两个串口,串口1会接收到设备大量的GB2312编码数据,每一帧数据以0x0D结尾,当串口1接收到一帧数据后,由串口2发送到上位机,上位机显示。本篇就如何缓存串口1发送来的数据,使串口2能正确转发给上位机做...

    背景

    下位机有两个串口,串口1会接收到设备大量的GB2312编码数据,每一帧数据以0x0D结尾,当串口1接收到一帧数据后,由串口2发送到上位机,让上位机显示。本篇就如何缓存串口1发送来的数据,使串口2能正确转发给上位机做个记录。

    正文

    • 逻辑没问题但实际有问题的做法
      由于设备发送到串口1的编码数据显示的是设备当前各种状态,因此每帧数据大小不定,而且什么时候发送也不确定,所以,串口1需要建立一个缓存区,缓存数据,接收到帧尾0x0D后,将串口1缓存区的数据copy到串口2发送缓存区,主循环随时监测串口2发送状态,并随时准备转发。
      实际运行效果却差强人意,会碰到数据被覆盖的情况,即当串口2在主循环发送数据时,此时串口1又来数据了,那么就会覆盖掉串口2发送缓存区内的数据。

    • 改进做法
      在串口1做两个接收缓存区,串口1收到数据后,将数据保存进缓存区1,主循环串口2开始发送数据串口1缓存区1的数据,并将串口1的接收缓存区切换到缓存区2,发送完串口1缓存区1后,如若串口1接收到完整帧,则主循环会发送串口1缓存区2的数据,并将串口1的接收缓存区切换到缓存区1。
      此处需要注意到一点,当串口1的缓存区2接收到帧尾0x0D时,会置位串口1标志位可以发送,此时如若串口1在接收到帧尾后的第一条数据时,应检测串口1的标志位是否处于可发送状态,并判定接收缓存区是否和上次相同,如若相同,说明主循环还未发送完缓存区1内的数据,此时应将可以发送的标志位置位回FALSE状态,避免接收缓存区2内接收到一部分数据,接收缓存区1又接收到另外一部数据。

    • 源代码
      由于这种实现方式标志位会比较多,不太好阅读,因此源代码不再贴出,记录并分享此方法为主。

    至此记录完毕。

    参考链接

    记录时间:2017-6-12
    记录地点:江苏淮安

    转载于:https://www.cnblogs.com/ChYQ/p/6991398.html

    展开全文
  • STM32串口发送乱码问题 小编是一个嵌入式初学者,才学没多久,将近两个月样子,在学习过程中遇到了一些问题,在这里给大家分享一下解决方案。...2) 串口调试助手接收数据的波特率与串口初始化时波特率不一致(这种
  • 7天快速入门Zigbee:串口透传数据

    千次阅读 多人点赞 2018-07-26 20:19:22
     这篇文章主要是想大家了解如何配置Z-Stack中串口功能参数,如何开启串口功能,如何使用串口发送接收功能,最后实现我们要的串口透传功能。 2. 配置串口参数,开启串口功能  在Z-Stack中我们可以直接...
  • 读取串口数据画图

    千次阅读 2012-02-21 16:45:14
    他的要求是自定义串口属性,上位机发送命令,然后读取每次8096bytes的回复数据,然后利用接收的数据画图,做一些统计和计算。自己做的过程中将问题分解了下: 1串口读取数据 2、读取的串口数据存储到txt中 3...
  • // 等待1秒钟让串口数据全部接收后在处理 Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } switch (serialPortEvent.getEventType()) { case ...
  • 主要思路是在串口通信助手中发送1”,然后串口接收中断打开,在串口通信助手中打印“中断开始”信息。但是这句“中断开始”信息没有显示,想请大佬看看shi'wei'shen'm usart.c ``` #include "stm32f10x.h" ...
  • 配送一个自己写的串口驱动程序 用DMA接收数据 接收完会产生一个空闲中断 由此可判断接收完一个包的数据 再配送一个我自己写的动态内存管理 跟ESP8266的驱动 在项目中测试460800的波特率 30kb一秒的数据接收 一包...
  • MX虚拟串口

    2019-04-17 07:07:20
    4. 【串口群组 】:向群组中任何串口发送数据,其它串口都能接收到。 5. 【串口客户端】:串口转tcp客户端,方便实现远程串口应用。 6. 【串口服务端】:tcp服务端转串口,安装在云服务器上,可与DTU直接串口互通。
  • <p> 大家好,有一个关于51单片机问题想请教一下,51开发版外接了一HC06蓝牙模块,然后再手机串口软件上发送1程序直接跳到step3,发送二直接跳到step5,这样写程序可以吗? </p><p> 不可以话希望可以给出修改...
  • 1 先使用可视化的软件“串口调试助手V2.2”设定 串口、波特率、校验位、数据位、停止位、然后发送命令,查看接收的 结果 下载地址 2为了更好侦听、拦截、记录、分析串行通信协议,可以使用这个软件“侦听...
  • 串口监视工具 v6.72.zip

    2019-07-14 19:59:26
    软件可以侦测、拦截、逆向分析串口通信协议,监视电脑串口活动,显示波特率和状态,并能保存日志记录,您对应用程序操作串行端口的过程和细节,您及时的模拟被侦听程序或设备的数据、控制流,提高工作效率。串口...
  • Awen串口调试助手

    2018-07-03 15:58:31
    Awen串口调试助手。。。。。。。打开串口调试助手,设置COM1的波特率、奇偶校验位、数据位、停止...我们这样设置,是为了COM1负责发送数据,COM2负责接收数据。如果COM2也被占用,那么你程序就无法使用这个端口了。
  •  51单片机串口不同寻常特征是包括第9位方式(在串口模式2和模式3下)。它允许把在串行口通信增加第9位用于标志特殊字节的接收。一般约定第9位为高时表示该字节为地址字节,第9位为低时为数据字节。第9位方式允许...
  • Linux下的串口助手(可以调AT指令)

    热门讨论 2011-11-30 09:50:46
    1:串口打开格式一般为8N1(8位数据位,无校验位,1停止位)无流控制; 2:如果想让数据以16进制显示,请勾选HEX; 3:如果勾选上《回车》功能,那么每次接收数据就在后面加个回车符; 4:如果想定时发送数据那么请...
  • 一、基本使用 ESP32有三个串口,编号分别为0、12。这里不多解释。 输出“hello world”...然后我们将串口数据的接收发送程序下载到开发板(详情见上一期) #include <HardwareSerial.h> Hard...
  • ECOM串口助手

    热门讨论 2011-09-02 23:43:34
    接收发送任何数据或字符(包括中文),能发送任意大小文本文件,可以任意设定自动发送周期, 并能将接收数据保存成文本文件。 是工程师调试单片机串口的好助手工具。 2、软件特点 1、 支持Windows 9x / 2000 ...
  • TCP串口调试软件

    2013-11-16 10:16:16
    1.接收串口进来的数据并在窗口显示. 2.所接收的数据数据显示方式可以选择为字符方式或者HEX方式 4.中文显示无乱码,且不影响速度 5.串口波特率可以选择为110bps-256000bps.(波特率>115200时需要硬件支持) 6.可以...
  • 玩stm32也有一段时间了,对串口中断接受和DAM方式发送总一下总结,但是本节只讲述串口中断接受基本配置,既然是基本就说明他很重要,如有疏忽,就会让串口失灵。下一节主要讲述DAM用法。言归正传:首先我们要...
  • 这是我代码,将之烧入51单片机时,串口通信本来是led显示,但是可能由于红外遥控中断函数干扰了串口通信,导致红外遥控工作正常,串口通信无法进行,led无法显示。 #include #include<intrins.h> ...
  • <br />主机信息可以发到各个从机,从机发送的信息只能被主机...用这种方式,主机首先广播1字节,并其第9位为高,同时收到该字节的各个从机,只有地址相符的打开,以接收后面的数据字节。所接续的数据字节(第
  • //选择定时器2串口1的波特率发生器 ES =1; //使能串口中断 EA =1; //开启总中断 } void UART_Sendchar(unsigned char dat) //串口发送函数 { while(busy); busy=1; SBUF=dat; } ...

空空如也

空空如也

1 2 3 4
收藏数 64
精华内容 25
关键字:

串口1接收的数据让串口2发送