精华内容
下载资源
问答
  • 1. UART串口协议以及串口发送端设计2 发送多个字节 1.1 串口协议发送端设计_多个字节 (1). 串口协议发送端整体框图 目标:按键控制串口发送“HELLO”字符串 知识点: wait函数调用 发送字符串的方法:控制输入...

    FPGA学习笔记

    1. UART串口协议以及串口发送端设计2

    • 发送多个字节

    1.1 串口协议发送端设计_多个字节

    (1). 串口协议发送端整体框图

    在这里插入图片描述

    目标:按键控制串口发送“HELLO”字符串

    知识点:

    1. wait函数调用
    2. 发送字符串的方法:控制输入数据,每个字节(8bits)发一次,连续发多次
    3. 层次的引用:调用例化后的信号名称.变量(test_bench内)

    (3). Verilog 代码

    //----top---------------------------------------
    module uart_tx_multbyte#(
    	parameter byte1 = "H",
    	parameter byte2 = "E",
    	parameter byte3 = "L",
    	parameter byte4 = "L",
    	parameter byte5 = "O",
    	parameter byte6 = "\n"
    )
    (
    	input clk,
    	input rst_n,
    	input key0,
    	output led,
    	output rs232_tx
    );
    	reg send_en;
    	reg [7:0] data_byte;
    	wire key_state0;
    	wire key_flag0;
    	reg [2:0] cnt_byte;
    	wire tx_done;
    	
    	uart_tx_r0 uut_uart(
    		.clk(clk),
    		.rst_n(rst_n),
    		.send_en(send_en),
    		.baud_set(3'd4),
    		.tx_done(tx_done),
    		.data_byte(data_byte),
    		.uart_state(led),
    		.rs232_tx(rs232_tx)
    	);
    	
    	fsm_key_filter uut_key(
    			.clk(clk),
    			.rst_n(rst_n),
    			.key(key0),
    			.key_state(key_state0),
    			.key_flag(key_flag0)
    );
    
    //----counter--------------------------------------	
    	always@(posedge clk or negedge rst_n)
    		if(!rst_n)
    			cnt_byte <= 0;
    		else if(tx_done)
    			cnt_byte <= cnt_byte + 3'd1;
    		else if(key_flag0 & ! key_state0)
    			cnt_byte <= 3'd0;
    //---------send_en---------------------------------			
    	always@(posedge clk or negedge rst_n)
    		if(!rst_n)
    			send_en <= 0;
    		else if(key_flag0 & ! key_state0)//press key
    			send_en <= 1;
    		else if(tx_done &(cnt_byte <= 3'd5))
    			send_en <= 1;
    		else
    			send_en <= 0;
    			
    //----data----------------------------------------
    	always@(*)
    		case(cnt_byte )
    			3'd0: data_byte <= byte1;
    			3'd1: data_byte <= byte2;
    			3'd2: data_byte <= byte3;
    			3'd3: data_byte <= byte4;
    			3'd4: data_byte <= byte5;
    			3'd5:	data_byte <= byte6;	
    			default: data_byte <= 0;
    		endcase
    endmodule
    

    按键消抖模块代码

    //----按键以及抖动滤除----------------------------
    module fsm_key_filter#(
    	parameter IDLE = 4'b0001,
    	parameter FILTER1 = 4'b0010,
    	parameter DOWN = 4'b0100,
    	parameter FILTER2 = 4'b1000
    )
    (
    	input clk, //50MHz 20us
    	input rst_n,
    	input key,
    	
    	output  key_flag,
    	output reg  key_state
    );
    	reg		cnt_en;
    	reg		cnt_full;
    	reg [19:0] cnt1;
    	//reg [19:0] cnt2;
    	reg [3:0] state;
    	reg		key_syn1;
    	reg		key_syn2;
    	reg 		key_reg1;
    	reg		key_reg2;
    	wire 		pos_edge;
    	wire 		neg_edge;
    	
    	always@(posedge clk or negedge rst_n)
    		if(!rst_n)begin
    			state <= IDLE;
    			cnt_en <= 1'b0;
    		end else 
    		begin
    			case(state)
    				IDLE:
    					begin
    						if(neg_edge)begin
    							state <= FILTER1;
    							cnt_en <= 1'b1;
    						end else
    						begin
    							state <=	IDLE;	
    							cnt_en <= 1'b0;
    						end
    					end
    					
    				FILTER1:
    					begin
    							if(cnt_full)//20ms
    							begin
    								state <= DOWN;
    								cnt_en <= 1'b0;
    							end 
    							else if(pos_edge)
    							begin
    								state <= IDLE;
    								cnt_en <= 1'b0;
    							end else
    							begin
    								state <= FILTER1;
    								cnt_en <= cnt_en;
    							end
    					end
    					
    				DOWN:
    					begin
    						if(pos_edge)begin
    							cnt_en <= 1'b1;
    							state <= FILTER2;
    						end else 
    						begin
    							cnt_en <= 1'b0;
    							state <= DOWN;
    						end
    					end
    					
    				FILTER2:
    					begin
    							if(cnt_full)
    								state <=	IDLE;	
    							else if(neg_edge)begin
    								cnt_en <= 1'b0;
    								state <= DOWN;
    							end 
    							else
    								state <= FILTER2;
    					end
    				default: begin
    					state <= IDLE;
    					cnt_en <= 1'b0;
    				end
    			endcase
    		end
    //----cnt--------------------------------------
    	always@(posedge clk or negedge rst_n)begin
    		if(!rst_n)
    			cnt1 <= 20'd0;
    		else if(cnt_en)
    			cnt1 <= cnt1 + 20'd1;
    			else 
    			cnt1 <= 20'd0;
    	end
    	always@(posedge clk or negedge rst_n)begin
    		if(!rst_n)
    			cnt_full <= 1'b0;
    		else if(cnt1 == 20'd999_999)
    			cnt_full <= 1'b1;
    			else 
    			cnt_full <= 1'b0;
    	end
    //----asyn_key-->syn---------------------------------
    	always@(posedge clk or negedge rst_n)begin
    		if(!rst_n)begin
    			key_syn1 <= 1'b0;
    			key_syn2 <= 1'b0;
    		end else
    		begin
    			key_syn1 <= key;
    			key_syn2 <= key_syn1;
    		end	
    	end
    //----key edge detect--------------------------------
    	always@(posedge clk or negedge rst_n)begin
    		if(!rst_n)begin
    			key_reg1 <= 1'b0;
    			key_reg2 <= 1'b0;
    		end else
    		begin
    			key_reg1 <= key_syn2;
    			key_reg2 <= key_reg1;
    		end	
    	end
    	assign neg_edge = (!key_reg1) & key_reg2;
    	assign pos_edge = key_reg1 & (!key_reg2);
    	
    //----key_flag---------------------------------------
    	assign key_flag = (cnt1 == 20'd999_999)? 1'b1:1'b0;
    //----key_state--------------------------------------
    		always@(posedge clk or negedge rst_n)
    			if(!rst_n)
    				key_state <= 1;
    			else if(cnt_full)
    				key_state <= ~key_state;
    			else
    				key_state <= key_state;	
    endmodule
    

    //------------------------------------------------
    //单一字节串口发送
    UART串口协议以及串口发送端设计1
    //------------------------------------------------

    测试平台testbench

    //----testbench-----------------------------------
    `timescale 1ns/1ns
    `define clk_period 20
    
    module uart_tx_multbyte_tb;
    	reg     clk;
    	reg     rst_n;
    	wire    key0;	
    	wire	rs232_tx;
    	reg     press;
    	wire    led;
    	
    	uart_tx_multbyte uut(
    		.clk(clk),
    		.rst_n(rst_n),
    		.key0(key0),
    		.led(led),
    		.rs232_tx(rs232_tx)
    	);
    	key0_model uut_model(
    		.press(press),
    	   .key(key0)
    );
    	initial 
    		clk = 1;
    	always begin #(`clk_period/2) clk = ~clk;end
    	
    	initial begin
    		rst_n = 0;
    		press = 0;
    	#(`clk_period*20+1)
    		rst_n = 1;
    	#(`clk_period*20+1);
    		press = 1;
    	#(`clk_period*20+1);
    		press = 0;
    		
    	wait(uut.tx_done &(uut.cnt_byte == 3'd5));
    	
    	#(`clk_period*200+1);
    	$stop;
    	end
    endmodule
    //----key0_model-------------------------------
    `timescale 1ns/1ns
    module key0_model(
    	input		press,
    	output      reg key
    );
    	reg [15:0] myrand;
    	
    	initial begin
    		key = 1;//before press
    	end
    	always@(posedge press)
    		press_key;
    		
    task press_key;
    	begin
    		repeat(50)begin
    		myrand = {$random}%65536;//{$random}%6553(0~65535);{random}%65536:(-65535~65535)
    		#myrand; key = ~key;			
    	   end
    	   key = 0;
    		#50000000;
    		
    		repeat(50)begin
    		myrand = {$random}%65536;//0~65535;
    		#myrand; key = ~key;			
    	   end
    	   key = 1;
    		#25_000_000;
    	   	
    	end
    	endtask
    endmodule
    
    

    (3). Modelsim仿真

    在这里插入图片描述
    (4). FPGA板级验证

    将代码通过JTAG下载到FPGA开发板中
    在这里插入图片描述
    打开串口调试助手,设置串口,波特率,接受设置为ASCII码的形式,点击开始。在FPGA上进行按键,每按一次,串口接受窗口将显示发送的数据“HELLO”。

    在这里插入图片描述


    ----学习内容来自小梅哥FPGA视频
    【注】:个人学习笔记,如有错误,望不吝赐教,这厢有礼了~~~


    展开全文
  • python虚拟串口模块serial安装1.下载软件包:https://pypi.python.org/pypi/pyserial?#downloads2.解压:tar -zxvf pyserial-3.4.tar.gz3.进入解压目录:cd pyserial-3.4/ 4.安装sudo python setup.py install(这里...

    python虚拟串口模块serial安装

    1.下载软件包:https://pypi.python.org/pypi/pyserial?#downloads

    2.解压:tar -zxvf pyserial-3.4.tar.gz

    3.进入解压目录:cd pyserial-3.4/

    4.安装sudo python setup.py install(这里以ubuntu为例,其他linux操作系统可切换在root权限下进行安装操作)

    程序设计需求

    【虚拟串口的建立形式】
    根据python serial库的特殊性质,它可以产生两个相互短接的虚拟串口,通过对这两个串口进行读写,可以实现消息的收发。因此,笔者进行学习调研后,在下面的代码中,运用这个serial库的相关函数,打开了一个虚拟串口,同样也实现了发送端和接收端在同一个串口进行收发消息的功能。
    由虚拟串口实现原理可以发现,它的设计是一个while(true)死循环,因为它要不停地检测在此串口下的数据流。

    【发送端程序实现形式】
    代码编写语言:python
    对于串口实现的消息收发,python也有os.read()os.write()这类针对数据读写的函数,因此发送端的设计采用raw_input()接收来自终端的消息,通过os.write()写入串口内的缓存,同时通过os.read()一次性读取接收端反馈的消息;

    另外,考虑到实际工程需求,笔者将虚拟串口和发送端集成到一起,这样一来,只需要运行集成后的发送端代码,就可以同时开启虚拟串口和发送消息;

    考虑到虚拟串口建立是一个不能被中断的死循环,因此,在集成代码时,将虚拟串口的建立作为父线程。要实现不停发送消息的工程需求,发送端也是一个死循环,它作为子线程依赖于父线程运行,一旦子线程break了,父线程发现子线程死了,那么父线程也结束。

    【接收端验证程序】
    代码编写语言采用C语言
    设计模式是:接收端一旦在串口中读到数据,则向串口中发回执消息,向发送端通知消息已经成功接收。

    python虚拟串口代码分析

    下面的代码是笔者在补充学习python serial虚拟串口建立过程中,淘到的有意思的代码,贴出来做一个分享,同时结合笔者在开发过程中遇到的问题,对代码做一些浅显的分析。(后面笔者贴出的发送端代码也是基于这个代码的学习进行编写的)

    #! /usr/bin/env python
    #coding=utf-8
    import pty
    import os
    import select
    
    def mkpty():
        master1, slave = pty.openpty()
        slaveName1 = os.ttyname(slave)
        master2, slave = pty.openpty()
        slaveName2 = os.ttyname(slave)
        print '\nslave device names: ', slaveName1, slaveName2
        return master1, master2
    
    if __name__ == "__main__":
    
        master1, master2 = mkpty()
        while True:
            rl, wl, el = select.select([master1,master2], [], [], 1)
            for master in rl:
                data = os.read(master, 128)
                print "read %d data." % len(data)
                if master==master1:
                    os.write(master2, data)
                else:
                    os.write(master1, data)

    笔者的理解:

    在创建虚拟串口的mkpty()函数中,master, slave = pty.openpty() 方法用于打开一个新的伪终端对。在调试程序时发现,若改成在slave端进行消息的收发, 发现消息发不出去,当然也收不到回执的OK消息,python发送端和c接收端的收发都是read/write,说明master是read/write、slave是port_recv, 也就是说 pty对应master ,用于read write ;tty对应slave用于port_recv

    为避免别的设备占用tty的slave口,笔者曾想着把slave这个端口强制关闭。

    pty.openpty()分别为主机和从机端返回一对文件描述符(pty,tty)。后来对这两个描述符进行思考发现:
    pty,tty描述符分析
    master和slave就像钥匙一样,它俩其实是随机的,跟最终生成的端口没有必然的规律。但是发送方和对端只有匹配了master和slave,才能打开它俩建立的“锁”—-/dev/pts/num。所以,根据这个发现,别的设备不会与我的指定设备占用tty的slave口,也不用关闭slave口,否则发送方就没法与对端通过master和slave建立的虚拟端口通信了

    从实际测试来看,创建虚拟串口虽然随机,但是不会同时建两个一样的串口,只要最终创建的虚拟串口不同,slave1和slave2即使相同也不会占用。

    serial虚拟串口建立+发送端python实现

    笔者经过思考后,对上面的代码进行修改,结合实际的工程需求,将建立虚拟串口和消息的发送集成到了一起,通过开辟不同的线程,让两者能同时正常运行。
    下面贴出源代码:

    import serial
    import sys
    import pty
    import os
    import time
    import select
    from time import ctime
    from time import sleep
    import threading  #multi thread working mode
    
    #send & recv msg using mkpty port
    def Vpsend(slaveName,master): #slaveName is the parameter from mkpty()
        print "\n"
        print " Open the port.Please Waiting...\n"
        sleep(1) 
        ser=serial.Serial(slaveName,9600,timeout=0.5) #pass parameter:slaveName
        print "Open port successful! the port information:"
        print ser
        print "\n"
        while ser.isOpen(): #the return is True or Faulse
            print "please write the msg(exit to break)"
            msg=raw_input()
    
            #add a break reason:::kill the child thread
            if msg == 'exit':
                print "\n"
                print "Please waiting to close the connection......"
                sleep(1)
                break;  
    
            msg=msg + '\r' + '\n'  #AT form define
    
            #data=ser.write(msg)
        os.write(master, msg)
            sys.stdout.flush()  #flush the buffer
            print "\n"
            print ("waiting to recv the data...")
            sleep(2)
        msg_recv = os.read(master,128)
            print ("\n")
            print ("\tOK! The recv msg is %s"%(msg_recv))
    
    #create only one virtual port
    def mkpty():
        #make pair of pseudo tty
        master, slave = pty.openpty()
        slaveName = os.ttyname(slave)
    
        print "slave device names:", slaveName
    
        #set the Vpsend() as the child thread and set the 'slaveName' as pass parameter, Vpsend will use 'slaveName'
        t=threading.Thread(target=Vpsend,args=(slaveName,master))
        t.start()   #start this thread
        while True:
            sleep(1)
            if t.is_alive() == False:  #when the child thread killed, then this father thead break...
                break
    mkpty()
    
    

    (ps:由于实际工程平台中文会产生乱码,英文注解有点蹩脚,稍微将就一下。。。)

    在设计上面代码的时候,笔者发现:

    原参考的创建虚拟串口代码中,主线程里本身就有对该串口进行os.read和os.write的读写操作,再加上子线程也有对此串口的ser.read和ser.write读写操作,以及对端(接收端)对串口中的数据的read和write操作,使得子线程在接收对端数据时,会与主线程的os.read产生竞争。

    针对此,笔者的解决方案是:删除主线程里对串口进行os.read和os.write的读写操作,只保留子线程与对端的通信联系。

    接收端C代码实现

    为了测试我们的发送端主代码是否能正常工作,笔者设计了一个C的接收程序,源代码如下:

    代码中,默认打开的端口是3,可以在命令行传参更改打开端口,执行命令如下:
    gcc receive.c -o recv
    ./recv -p 4 //假设发送端打开的端口是4,接收端也打开4才能与发送端通信

    //receive.c
    #include <stdio.h>
    #include <string.h>
    #include <malloc.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <termios.h>
    #include <math.h>
    #include <stdlib.h>
    #define MAX_BUFFER_SIZE 512
    int fd, s;
    char * g_pts = "/dev/pts/3";
    int opt = -1;
    
    /*open port*/
    int open_port()
    {
        fd = open(g_pts, O_RDWR|O_NOCTTY|O_NDELAY);
        if(fd == -1)
        {
            perror("open serial port error!\n");
            return -1;
        }
        printf("open /dev/ttyS0.\n");
        return 0;
    }
    
    int main(int argc, char* argv[])
    {
        char hd[MAX_BUFFER_SIZE], *rbuf;
        int flag_close, result;
        struct termios option;
    
        while((opt = getopt(argc, argv,"p:")) != -1)
        {
            switch(opt)
            {
                case 'p':/*hook bind pts number*/
                    {
                    char pts[] = "/dev/pts/0";
                    int len = sizeof(pts);
                    char * tmp = (char *)malloc(100*sizeof(char));
                    memcpy(tmp, pts, len);
                    char * rec = optarg;
                    strcpy(tmp+len-2,rec );
                    g_pts = tmp;
                    break;
                    }
                case '?':
                case 'v':
                default:
                    printf("UnKnown option\n");
                    break;
    
            }
        }
        fprintf(stderr, "Current option is:\n");
        fprintf(stderr, "\t -p MES AT com port Num:    %s  (default: 3) \n", g_pts);
    
        /*open port*/
        result = open_port();
        if(result < 0)
        {
            printf("Open port error!\n");
            return -1;
        }
    
        /*welcome msg*/
        printf("open %s port successfully!!!~~~biubiubiubiubiu~~~\n", g_pts);
        printf("******OK~~ let's start to recv msg from the other side~~~********");
        printf("\n");
    
        /*port set*/
        tcgetattr(fd, &option);
        cfmakeraw(&option);
        cfsetispeed(&option, B9600);
        cfsetospeed(&option, B9600);
        tcsetattr(fd, TCSANOW, &option);
        rbuf = hd;
        memset(rbuf,'\0', 10);
        printf("Ready for receiving data...\n");
    
        /*star to recv msg*/
        char get_buffer[1024];
        memset(get_buffer, '\0', 1024);
        printf("fd = %d\n", fd);
        while(1)
        {
            while((result = read(fd, (void *)get_buffer, 1023)) > 0)
            {
                printf("%s\n", get_buffer);
                memset(get_buffer, '\0', 1023);//clean the buffer to get the new full msg
    
                /*send the feedback msg to the sender*/
                char ans[100];
                int reply = 0;
                int re_len = 0;
                strcpy(ans,"######[Attention]From recv fb msg::: OK,your msg has been recvd!\n");
                re_len = strlen(ans);
                reply = write(fd, ans, re_len);
            }
        }
    
        printf("\n");
        flag_close = close(fd);
        if(flag_close == -1)
        printf("Close the device failure!\n");
        return 0;
    }

    代码连调结果

    连调中,发送端发了两次消息

    第一个消息是:msg1
    第二个消息是:hello my name is tmw

    消息均成功发到接收端,并且收到接收端回执消息。

    代码连调结果

    下图是跳出发送代码的调试结果:

    跳出循环


    梦想还是要有的,万一实现了呢~~~~ヾ(◍°∇°◍)ノ゙

    展开全文
  • 串口发送32位的float型数据,pc进行四个8字节数据的接收及解码。代码中解码并存储了每个float行的二进制与之对应的十进制,修改路径即可。
  • 1.数据采用python中str()函数,转换为字符串格式,再串口接受对字符串进行解码例如python通过串口发送0x08数据至串口接受器,此时可以通过将0x08转换为str格式发送,再通过串口接收器解析代码将str转化为1...

    python通过调用serial库函数发送指令,其中串口通信发送的数据需要是str格式字符串。当需要给下方发送16进制数据时,必须将16进制数转化为str格式字符串方可发送。

    1.数据采用python中str()函数,转换为字符串格式,再串口接受端对字符串进行解码

    例如python通过串口发送0x08数据至串口接受器,此时可以通过将0x08转换为str格式发送,再通过串口接收器解析代码将str转化为16进制数。

    data=0x08

    serial.send(str(data))          注:str(0x18)='24'

    事实上这样的转化在串口接收器端会比较麻烦,因为使用串口调试助手时也无法进行解码。同时发送的数据量也偏大

    2.数据采用python中chr()函数,转换为ascII码形式,发送ascII码,对方接受后识别为16进制数据。

    data=0x08

    serial.send(chr(data))          注: chr(0x08)='\x08'具体为何chr()函数转换的16进制ascII数据可以被识别,需要认真探讨

    这个方式有一个很大的问题是chr的转换只能是0~255之间的数据,超过就无法解析成ascII码

    事实上 当print(chr(0x30))时打印出的是ascII编码的字符0,print(chr(48)也是字符0,与ascII字符表上的一致。

    3.同时还可以通过binascii.b2a_hex函数进行进制转换

    后面两种可行的方式归根究低是通过发送‘x08’这样的格式发送,实际上这个格式是通用的ascII码的格式。事实上系统将数据下达串口时会将数据进行解析,ascII码的数据解析为这个16进制对应的二进制码。即使发送的是字符串:‘hello’ 实际上也是通过ascII码的解析,将每一个字符解析成ASCII码的二进制数据,再发送过去。

    展开全文
  • STM32通过串口发送接收PC消息,并控制LED灯的亮灭

    千次阅读 多人点赞 2020-10-17 11:39:09
    STM32F407ZE 通过串口发送接收PC串口助手消息,并控制LED灯的亮灭 具体代码解析如下: ustart.h部分 #ifndef USTART_H #define USTART_H #include <stm32f4xx.h> #include <stm32f4xx_usart.h> #...

    STM32F407ZE 通过串口发送接收PC端串口助手消息,并控制LED灯的亮灭
    STM32串口USART1接收字符串
    具体代码解析如下:

    ustart.h部分

    #ifndef USTART_H
    #define USTART_H
    
    #include <stm32f4xx.h>
    #include <stm32f4xx_usart.h>
    #include "sys.h"
    
    void USART1_Init();
    void USART_SendString(USART_TypeDef* USARTx, char *DataString);
    #endif
    

    ustart.c部分

    #include "ustart.h"
    #include <string.h>
    
    void USART1_Init()
    {
    	GPIO_InitTypeDef 	GPIOInit_Struct;
    	USART_InitTypeDef 	USARTInit_Struct;
    	
    	//1、使能时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    	
    	//2、初始化对应的IO引脚复用为USART1功能
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    	
    	GPIOInit_Struct.GPIO_Pin 	= GPIO_Pin_9 | GPIO_Pin_10;
    	GPIOInit_Struct.GPIO_Mode	= GPIO_Mode_AF;
    	GPIOInit_Struct.GPIO_OType	= GPIO_OType_PP;
    	GPIOInit_Struct.GPIO_Speed 	= GPIO_Fast_Speed;
    	GPIOInit_Struct.GPIO_PuPd	= GPIO_PuPd_UP;
    	GPIO_Init(GPIOA,&GPIOInit_Struct);
    	
    	//将PA9  PA10复用为USART1功能
    	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
    	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
    	
    	//3、USART1初始化
    	USARTInit_Struct.USART_BaudRate 	= 115200; 								//波特率
    	USARTInit_Struct.USART_Parity		= USART_Parity_No;						//无校验位
    	USARTInit_Struct.USART_StopBits		= USART_StopBits_1;						//1位停止位
    	USARTInit_Struct.USART_WordLength	= USART_WordLength_8b;					//8位数据位
    	USARTInit_Struct.USART_Mode			= USART_Mode_Rx | USART_Mode_Tx;		//收发模式
    	USARTInit_Struct.USART_HardwareFlowControl	= USART_HardwareFlowControl_None;//无硬件控制流
    	USART_Init(USART1,&USARTInit_Struct);
    	
    	//4、开启串口
    	USART_Cmd(USART1,ENABLE);
    }
    
    void USART_SendString(USART_TypeDef* USARTx, char *DataString)
    {
    	int i = 0;
    	USART_ClearFlag(USARTx,USART_FLAG_TC);										//发送字符前清空标志位(否则缺失字符串的第一个字符)
    	while(DataString[i] != '\0')												//字符串结束符
    	{
    		USART_SendData(USARTx,DataString[i]);									//每次发送字符串的一个字符
    		while(USART_GetFlagStatus(USARTx,USART_FLAG_TC) == 0);					//等待数据发送成功
    		USART_ClearFlag(USARTx,USART_FLAG_TC);									//发送字符后清空标志位
    		i++;
    	}
    }
    

    main.c部分(接收PC端发送来的单个字符)

    #include <stm32f4xx.h> 
    #include "led.h"
    #include "ustart.h"
    
    int main()
    {
    	LED_Init();															//LED灯初始化
    	USART1_Init();														//串口初始化
    	USART_SendString(USART1, "Hello world!\r\n");						//发送字符串
    	
    	char USART1_ReceiveData = 0;										//接收PC端发送过来的字符
    	USART_ClearFlag(USART1,USART_FLAG_RXNE);							//接收前先清空标志位
    	while(1)
    	{
    		if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) == 1)			//USART_FLAG_RXNE判断数据,== 1则有数据
    		{
    			USART1_ReceiveData = USART_ReceiveData(USART1);				//通过USART1串口接收字符
    			USART_ClearFlag(USART1,USART_FLAG_RXNE);					//接收后先清空标志位
    		}
    		
    		if( '1' == USART1_ReceiveData )									//如果数据为1,LED1灯电平翻转
    		{
    			PFout(9) = !PFout(9);
    		}
    		
    		if( '2' == USART1_ReceiveData )									//如果数据为2,LED2灯电平翻转
    		{
    			PFout(10) = !PFout(10);
    		}
    		USART1_ReceiveData = 0;											//数据清零
    	}
    }
    

    sys.h部分:

    #ifndef __SYS_H
    #define __SYS_H	 
    #include "stm32f4xx.h" 
    
    //IO口操作宏定义
    #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr & 0xFFFFF)<<5)+(bitnum<<2)) 
    #define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
    #define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
    //IO口地址映射
    #define GPIOA_ODR_Addr    (GPIOA_BASE+20) //0x40020014
    #define GPIOB_ODR_Addr    (GPIOB_BASE+20) //0x40020414 
    #define GPIOC_ODR_Addr    (GPIOC_BASE+20) //0x40020814 
    #define GPIOD_ODR_Addr    (GPIOD_BASE+20) //0x40020C14 
    #define GPIOE_ODR_Addr    (GPIOE_BASE+20) //0x40021014 
    #define GPIOF_ODR_Addr    (GPIOF_BASE+20) //0x40021414    
    #define GPIOG_ODR_Addr    (GPIOG_BASE+20) //0x40021814   
    #define GPIOH_ODR_Addr    (GPIOH_BASE+20) //0x40021C14    
    #define GPIOI_ODR_Addr    (GPIOI_BASE+20) //0x40022014     
    
    #define GPIOA_IDR_Addr    (GPIOA_BASE+16) //0x40020010 
    #define GPIOB_IDR_Addr    (GPIOB_BASE+16) //0x40020410 
    #define GPIOC_IDR_Addr    (GPIOC_BASE+16) //0x40020810 
    #define GPIOD_IDR_Addr    (GPIOD_BASE+16) //0x40020C10 
    #define GPIOE_IDR_Addr    (GPIOE_BASE+16) //0x40021010 
    #define GPIOF_IDR_Addr    (GPIOF_BASE+16) //0x40021410 
    #define GPIOG_IDR_Addr    (GPIOG_BASE+16) //0x40021810 
    #define GPIOH_IDR_Addr    (GPIOH_BASE+16) //0x40021C10 
    #define GPIOI_IDR_Addr    (GPIOI_BASE+16) //0x40022010 
     
    //STM32中  对寄存器的访问  是不能单独访问寄存器的单个bit  只能以32bit地址访问寄存器
    //这些位为只写形式,只能在字(word)--4byte、半字2byte 或字节模式下访问 
    //IO口操作,只对单一的IO口!
    //确保n的值小于16!
    #define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
    #define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 
    
    #define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
    #define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 
    
    #define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
    #define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 
    
    #define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
    #define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 
    
    #define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
    #define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入
    
    #define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
    #define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入
    
    #define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
    #define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入
    
    #define PHout(n)   BIT_ADDR(GPIOH_ODR_Addr,n)  //输出 
    #define PHin(n)    BIT_ADDR(GPIOH_IDR_Addr,n)  //输入
    
    #define PIout(n)   BIT_ADDR(GPIOI_ODR_Addr,n)  //输出 
    #define PIin(n)    BIT_ADDR(GPIOI_IDR_Addr,n)  //输入
    
    
    #endif
    

    开启串口终端接收PC端串口助手发送过来的字符

    ustart.c部分

    #include "ustart.h"
    #include <string.h>
    
    void USART1_Init()
    {
    	GPIO_InitTypeDef 	GPIOInit_Struct;
    	USART_InitTypeDef 	USARTInit_Struct;
    	NVIC_InitTypeDef  	USARTNVIC_Struct;
    	
    	//1、使能时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    	
    	//2、初始化对应的IO引脚复用为USART1功能
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    	
    	GPIOInit_Struct.GPIO_Pin 	= GPIO_Pin_9 | GPIO_Pin_10;
    	GPIOInit_Struct.GPIO_Mode	= GPIO_Mode_AF;
    	GPIOInit_Struct.GPIO_OType	= GPIO_OType_PP;
    	GPIOInit_Struct.GPIO_Speed 	= GPIO_Fast_Speed;
    	GPIOInit_Struct.GPIO_PuPd	= GPIO_PuPd_UP;
    	GPIO_Init(GPIOA,&GPIOInit_Struct);
    	
    	//将PA9  PA10复用为USART1功能
    	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
    	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
    	
    	//3、USART1初始化
    	USARTInit_Struct.USART_BaudRate 	= 115200; 								//波特率
    	USARTInit_Struct.USART_Parity		= USART_Parity_No;						//无校验位
    	USARTInit_Struct.USART_StopBits		= USART_StopBits_1;						//1位停止位
    	USARTInit_Struct.USART_WordLength	= USART_WordLength_8b;					//8位数据位
    	USARTInit_Struct.USART_Mode			= USART_Mode_Rx | USART_Mode_Tx;		//收发模式
    	USARTInit_Struct.USART_HardwareFlowControl	= USART_HardwareFlowControl_None;//无硬件控制流
    	USART_Init(USART1,&USARTInit_Struct);
    	
    	//开启串口中断
    	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
    	
    	USARTNVIC_Struct.NVIC_IRQChannel = USART1_IRQn;//stm32f4xx.h
    	USARTNVIC_Struct.NVIC_IRQChannelPreemptionPriority = 0;
    	USARTNVIC_Struct.NVIC_IRQChannelSubPriority        = 0;
    	USARTNVIC_Struct.NVIC_IRQChannelCmd	= ENABLE;
    	NVIC_Init(&USARTNVIC_Struct);
    	
    	//4、开启串口
    	USART_Cmd(USART1,ENABLE);
    }
    
    void USART_SendString(USART_TypeDef* USARTx, char *DataString)
    {
    	int i = 0;
    	USART_ClearFlag(USARTx,USART_FLAG_TC);										//发送字符前清空标志位(否则缺失字符串的第一个字符)
    	while(DataString[i] != '\0')												//字符串结束符
    	{
    		USART_SendData(USARTx,DataString[i]);									//每次发送字符串的一个字符
    		while(USART_GetFlagStatus(USARTx,USART_FLAG_TC) == 0);					//等待数据发送成功
    		USART_ClearFlag(USARTx,USART_FLAG_TC);									//发送字符后清空标志位
    		i++;
    	}
    }
    
    void USART1_IRQHandler(void)													//串口中断执行函数
    {
    	char USART1_ReceiveData = 0;												//接收PC端发送过来的字符
    	
    	if(USART_GetFlagStatus(USART1,USART_IT_RXNE) == 1)							//USART_FLAG_RXNE判断数据,== 1则有数据
    	{		
    		USART1_ReceiveData = USART_ReceiveData(USART1);							//通过USART1串口接收字符
    		USART_ClearFlag(USART1,USART_IT_RXNE);									//接收后先清空标志位
    	}
    	
    	if( '1' == USART1_ReceiveData )												//如果数据为1,LED1灯电平翻转
    	{
    		PFout(9) = !PFout(9);
    	}
    	
    	if( '2' == USART1_ReceiveData )												//如果数据为2,LED2灯电平翻转
    	{
    		PFout(10) = !PFout(10);
    	}
    }
    

    ustart.h部分

    #ifndef USTART_H
    #define USTART_H
    
    #include <stm32f4xx.h>
    #include <stm32f4xx_usart.h>
    #include "sys.h"
    
    void USART1_Init();
    void USART_SendString(USART_TypeDef* USARTx, char *DataString);
    #endif
    
    展开全文
  • 串口调试助手C++源代码 可接收发送串口数据 带接收Echo回环到...具备接收回环功能,勾选后可将接收到的数据,延时后反馈到发送端,便于调试。 2.环境说明: 开发环境是Qt5.10.1,使用Qt自带的QSerialPort。源代码...
  • 51串口发送数据

    2021-01-20 15:33:45
    串口通信为串行通信方式,即每次只能发送一位,且为单工,一端固定为发送端,另一端为接收端。 51单片机的串口需要配置的寄存器可以直接通过STC-ISP这个软件配置,选择好晶振的频率和波特率直接生成就可以了 下面...
  • 1.1 串口协议发送端设计 目标:FPGA接收其他设备通过UART发送过来的数据。 实验现象:在Quartusz II中调用in system sources and probes editor工具,查看UART接收模块接受到的数据,数据有pc机发出。 知识点: ...
  • 编译环境:keil c51 代码功能:51单片机通过串口向电脑Python发送一个16进制数 注:代码内包含工程和代码文件
  • 基础实验5-USART串口发送实验 ...文章目录基础实验5-USART串口发送实验实验代码 实验代码 int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration------------------
  • UART模块可以划分为三个模块:接收端、发送端、以及波特率发生器。 首先我们来介绍接收端的实现: UART整体模块框图包括了RX端和TX端;RX端有 input UART_RXD,output uart_rx_en,output uart_rx_dat[7:0];TX端...
  • PIC单片机串口发送与按键

    千次阅读 2018-10-11 23:27:25
    这是我学习PIC单片机调试过程中尝试的PIC单片机串口发送实验,当按键RB0有按下时,num自加,同时RC0端口接的LED翻转,并把num的数传给发送寄存器发送至电脑,波特率为9600,4M晶振. 代码如下: #include&amp;lt;pic...
  • 敬请期待~阅读本文需要具有的技能:看过该系列前几篇文章或明白前几篇文章内容的可以明白字符串、字节码之间的区别了解串口的原理和使用文章篇幅较长,以下内容建议横屏查看,或在PC打开本文链接。官方demo代码...
  • 【注】该项目是我们团队参加2019届全国大学生FPGA大赛的作品,系统主要实现视频任意角度旋转。该项目最终晋级决赛,并获得紫光...4.5 ddr+串口联合测试4.5.1总体设计DDR的数据通过AXI总线进行数据传输。在前面章节...
  • 使用stm32f205调试串口通讯时,发现一个问题,上电后串口发送字符串的第一个字节会丢失,发送测试数据hello,接收收到的数据为:ello,第一个字符丢失。用示波器抓取波形,发现第一个数据的波型也是丢失的。 出现...
  • 这里主要讲assessPort这个工具的使用方法,所以代码方面就给官方给的 ...3、监控串口 4、设置传输波特率 5、在监控打开监控 6、在终端发送数据 7、查看发送的数据 这就是assessPort 的使用简单教程。 ...
  • 使用stm32f103调试串口通讯时,上电后发送的字符串的第一个字节丢失。 发送数据GpuSend("SPG(2);"); 接收收到的数据为:PG(2);,第一个字符丢失。 出现问题的代码如下: 但以前都未出现过这个问题,于是怀疑...
  • 最近闲来无事写了一个串口转...串口发送端代码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text
  • 如题,这里对数据的处理对于熟悉matlab各函数操作的同学来讲,是常规操作,但对于matlab新手或只是想借用matlab工具将存于PC文件中的数据通过串口发送出去的工程人员来说,由于对matlab软件比较陌生,实现各种功能...
  • PB串口通讯API源代码

    热门讨论 2008-04-01 08:59:46
    端口初始化成功后即可使用of_send(string sendstring)向串口发送数据,或使用of_read()读取串口数据。当串口有数据到达时,触发ue_received事件,该事件提供给用户用来存放读取串口数据的代码(值得注意的是,当数据...
  • 本博客主要记录了模块的定点传输模式,透传模式相对简单,可以参考大多数的串口通信代码。 什么是串口透传? 所谓串口透传,就是不管所传输的内容、数据协议形式。只是把需要传输的内容当成一组二进制数据完美地传输...
  • 矩阵按键控制代码 /************************************************************ 正面朝上黑引脚为行,白引脚为列 A、B 、C 、D 分别返回 10 11 12 13 *为 14 #为 15 0为 16 无按键按下返回0 ******************...
  • 1、材料准备与接线 硬件:掌控板、Arduino UNO板子、土壤湿度传感器,杜邦线、USB接口 软件:阿里云物联网平台、Mind+ 接线表 2、图形化编程代码截图如下 3、阿里云配置 进入到阿里云的物联网...网页 ...
  • 如果需要发送端不断地接收新的数据,而发送端的数据传输率低就需要一个缓冲器FIFO来缓冲数据。当你为别人做项目只是想实现功能而不想让自己的代码让别人看到,想保护自己的算法时,你可以用以下的方法。我使用的是...
  • 代码实现的功能:单片机通过串口和PC进行通话,单片机收到PC发过来的字符串后,原原本本的返回给PC。 所以关于串口的配置,以及如何实现单片机将字符串原原本本的返回给PC就不怎么说了,因为正点原子原...
  • 扫描和配对网上代码挺多的,这里就不贴了,主要说明3和4 建立蓝牙串口通道需要用到BluetoothSocket对象,建立串口通讯通道,BluetoothDevice对象createRfcommSocketToServiceRecord方法返回BluetoothSocket对象,...
  • 本文实例讲述python调用Moxa PCOMM Lite通过串口Ymodem协议实现发送文件的方法,该程序采用python 2.7编写。主要内容如下: ...以下是发送端的python代码: #encoding=utf-8 from ctypes import *

空空如也

空空如也

1 2 3 4 5 ... 15
收藏数 284
精华内容 113
关键字:

串口发送端代码