当前位置:文档之家› 电脑串口接收数据程序

电脑串口接收数据程序

电脑串口接收数据程序
电脑串口接收数据程序

本程序用于电脑串口接收数据

SerialPort.h #ifndef SERIALPORT_H_

#define SERIALPORT_H_

#include

#include "TChar.h"

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

/** 串口通信类

*

* 本类实现了监听发到指定串口的数据

*/

class CSerialPort

{

public:

CSerialPort(void);

~CSerialPort(void);

public:

/** 初始化串口函数

*

* @param: UINT portNo 串口编号,默认值为1,即COM1,注意,尽量不要大于9 * @param: UINT baud 波特率,默认为9600

* @param: char parity 是否进行奇偶校验,'Y'表示需要奇偶校验,'N'表示不需要奇偶校验

* @param: UINT databits 数据位的个数,默认值为8个数据位

* @param: UINT stopsbits 停止位使用格式,默认值为1

* @param: DWORD dwCommEvents 默认为EV_RXCHAR,即只要收发任意一个字符,则产生一个事件

* @return: bool 初始化是否成功

* @note: 在使用其他本类提供的函数前,请先调用本函数进行串口的初始化

* /n本函数提供了一些常用的串口参数设置,若需要自行设置详细的DCB 参数,可使用重载函数

* /n本串口类析构时会自动关闭串口,无需额外执行关闭串口

* @see:

*/

//bool InitPort(UINT portNo = 3, UINT baud = CBR_19200, char parity = 'N', UINT databits = 8, UINT stopsbits = 1, DWORD dwCommEvents = EV_RXCHAR);

bool InitPort(UINT portNo, UINT baud, char parity, UINT databits, UINT stopsbits, DWORD dwCommEvents);

/** 串口初始化函数

*

* 本函数提供直接根据DCB参数设置串口参数

* @param: UINT portNo

* @param: const LPDCB & plDCB

* @return: bool 初始化是否成功

* @note: 本函数提供用户自定义地串口初始化参数

* @see:

*/

bool InitPort(UINT portNo, const LPDCB& plDCB);

/** 开启监听线程

*

* 本监听线程完成对串口数据的监听,并将接收到的数据打印到屏幕输出* @return: bool 操作是否成功

* @note: 当线程已经处于开启状态时,返回flase

* @see:

*/

bool OpenListenThread();

/** 关闭监听线程

*

*

* @return: bool 操作是否成功

* @note: 调用本函数后,监听串口的线程将会被关闭

* @see:

*/

bool CloseListenTread();

/** 获取串口缓冲区中的字节数

*

*

* @return: UINT 操作是否成功

* @note: 当串口缓冲区中无数据时,返回0

* @see:

UINT GetBytesInCOM();

/** 读取串口接收缓冲区中的数据

*

*

* @param: unsigned char * lpInBuffer 存放读取数据的字符变量* @return: bool 读取是否成功

* @note:

* @see:

*/

bool MyReadFile(unsigned char *lpInBuffer);

private:

/** 打开串口

*

*

* @param: UINT portNo 串口设备号

* @return: bool 打开是否成功

* @note:

* @see:

bool openPort(UINT portNo);

/** 关闭串口

*

*

* @return: void 操作是否成功

* @note:

* @see:

*/

void ClosePort();

/** 串口监听线程

*

* 监听来自串口的数据和信息

* @param: void * pParam 线程参数

* @return: UINT WINAPI 线程返回值

* @note:

* @see:

*/

static UINT WINAPI ListenThread(void* pParam);

/** 串口句柄*/

HANDLE m_hComm;

/** 线程退出标志变量*/

static bool s_bExit;

/** 线程句柄*/

volatile HANDLE m_hListenThread;

/** 同步互斥,临界区保护*/

CRITICAL_SECTION m_csCommunicationSync; //!< 互斥操作串口

};

#endif //SERIALPORT_H_

/** 线程退出标志*/

bool CSerialPort::s_bExit = false; //CSerialPort::为自定义的前缀。

/** 当串口无数据时,sleep至下次查询间隔的时间,单位:秒*/

const UINT SLEEP_TIME_INTERVAL = 5; //定义UINT SLEEP_TIME_INTERVAL为一个常量。UINT:指无符号整数。

CSerialPort::CSerialPort(void)

: m_hListenThread(INVALID_HANDLE_VALUE)

//INVALID_HANDLE_VALUE 实际值等于-1

{

m_hComm = INVALID_HANDLE_VALUE;

m_hListenThread = INVALID_HANDLE_VALUE;

InitializeCriticalSection(&m_csCommunicationSync);

}

CSerialPort::~CSerialPort(void)

{

CloseListenTread();

ClosePort();

DeleteCriticalSection(&m_csCommunicationSync);

}

//初始化串口函数

bool CSerialPort::InitPort(UINT portNo /*= 1*/, UINT baud /*= CBR_9600*/, char parity /*= 'N'*/,

UINT databits /*= 8*/, UINT stopsbits /*= 1*/, DWORD dwCommEvents /*= EV_RXCHAR*/)

/** 临时变量,将制定参数转化为字符串形式,以构造DCB结构:串口通讯中的设置信息,如波特率,奇偶校验位等.... */

char szDCBparam[50];

sprintf_s(szDCBparam, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopsbits);

/** 打开指定串口,该函数内部已经有临界区保护,上面请不要加保护*/

if (!openPort(portNo))

{

return false;

}

/** 进入临界段*/

EnterCriticalSection(&m_csCommunicationSync);

/** 是否有错误发生*/

BOOL bIsSuccess = TRUE;

/**

设置输入缓冲区和输出缓冲区的大小都是1024.

*/

if (bIsSuccess )

{

bIsSuccess = SetupComm(m_hComm,1024,1024);

}

/** 设置串口的超时时间,均设为0,不使用超时限制*/

COMMTIMEOUTS CommTimeouts;

CommTimeouts.ReadIntervalTimeout = 0;

CommTimeouts.ReadTotalTimeoutMultiplier = 0;

CommTimeouts.ReadTotalTimeoutConstant = 0;

if (bIsSuccess)

{

bIsSuccess = SetCommTimeouts(m_hComm, &CommTimeouts);

}

DCB dcb;

if (bIsSuccess)

{

/** 获取当前串口配置参数,并且构造串口DCB参数*/

bIsSuccess = GetCommState(m_hComm, &dcb) && BuildCommDCB(szDCBparam, &dcb);

/** 开启RTS flow控制*/

dcb.fRtsControl = RTS_CONTROL_ENABLE;

}

if (bIsSuccess)

{

/** 使用DCB参数配置串口状态*/

bIsSuccess = SetCommState(m_hComm, &dcb);

}

/** 清空串口缓冲区*/

PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

/** 离开临界段*/

LeaveCriticalSection(&m_csCommunicationSync);

return bIsSuccess == TRUE;

}

//关闭串口

void CSerialPort::ClosePort()

{

if (m_hComm != INVALID_HANDLE_VALUE)

{

CloseHandle(m_hComm);

m_hComm = INVALID_HANDLE_VALUE;

}

}

//打开串口

bool CSerialPort::openPort(UINT portNo)

{

/** 进入临界段*/

EnterCriticalSection(&m_csCommunicationSync);

/** 把串口的编号转换为设备名*/

char szPort[50];

sprintf_s(szPort, "COM%d", portNo);

/** 打开指定的串口*/

m_hComm = CreateFileA(szPort, /** 设备名,COM1,COM2等*/ GENERIC_READ, /** 只读模式*/

0, /** 共享模式,0表示不共享*/

NULL, /** 安全性设置,一般使用NULL */

OPEN_EXISTING, /** 该参数表示设备必须存在,否则创建失败*/

FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, /**重叠方式*/

0);

/** 如果打开失败,释放资源并返回*/

if (m_hComm == INVALID_HANDLE_VALUE)

{

LeaveCriticalSection(&m_csCommunicationSync);

return false;

}

/** 退出临界区*/

LeaveCriticalSection(&m_csCommunicationSync);

return true;

}

//打开监听线程

bool CSerialPort::OpenListenThread()

{

/** 检测线程是否已经开启了*/

if (m_hListenThread != INVALID_HANDLE_VALUE)

{

/** 线程已经开启*/

return false;

}

s_bExit = false;

/** 线程ID */

UINT threadId;

/** 开启串口数据监听线程*/

m_hListenThread = (HANDLE)_beginthreadex(NULL, 0, ListenThread, this, 0, &threadId);

/** 检测线程是否开启或发生错误了*/

if (!m_hListenThread)

{

return false;

}

/** 设置线程的优先级,高于普通线程*/

if (!SetThreadPriority(m_hListenThread, THREAD_PRIORITY_ABOVE_NORMAL)) {

return false;

}

return true;

}

//关闭监听线程

bool CSerialPort::CloseListenTread()

{

if (m_hListenThread != INVALID_HANDLE_VALUE) {

/** 通知线程退出*/

s_bExit = true;

/** 等待线程退出*/

Sleep(10);

/** 置线程句柄无效*/

CloseHandle(m_hListenThread);

m_hListenThread = INVALID_HANDLE_VALUE;

}

return true;

}

//获取串口缓冲区的字节数

UINT CSerialPort::GetBytesInCOM()

{

DWORD dwError = 0; /** 错误码*/

COMSTAT comstat; /** COMSTAT结构体,记录通信设备的状态信息*/ memset(&comstat, 0, sizeof(COMSTAT));

UINT BytesInQue = 0;

/** 在调用ReadFile和WriteFile之前,通过本函数清除以前遗留的错误标志*/ if (ClearCommError(m_hComm, &dwError, &comstat))

{

BytesInQue = comstat.cbInQue; /** 获取在输入缓冲区中的字节数*/ }

return BytesInQue;

}

//串口监听线程

UINT WINAPI CSerialPort::ListenThread(void* pParam)

{

/** 得到本类的指针*/

CSerialPort *pSerialPort = reinterpret_cast(pParam);

// 线程循环,轮询方式读取串口数据

while (!pSerialPort->s_bExit)

{

/**获取串口输入缓冲区的字节数据*/

UINT BytesInQue = pSerialPort->GetBytesInCOM();

/** 如果串口输入缓冲区中无数据,则休息一会再查询*/ if (BytesInQue == 0)

{

Sleep(SLEEP_TIME_INTERVAL);

continue;

}

/** 读取输入缓冲区中的数据并输出显示*/

do

{

unsigned char lpInBuffer[1024];

if (pSerialPort->MyReadFile(lpInBuffer) == true)

{

/**将读取的数据显示到命令行窗口*/

cout << lpInBuffer;

continue;

}

} while (--BytesInQue);

}

return 0;

}

bool CSerialPort::MyReadFile(unsigned char *lpInBuffer)

{

DWORD dwBytesRead = 1024;

COMSTAT ComStat;

DWORD dwErrorFlags;

OVERLAPPED m_osRead; //创建OVERLAPPED结构。

memset(&m_osRead, 0, sizeof(OVERLAPPED));

m_osRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

ClearCommError(m_hComm, &dwErrorFlags, &ComStat); //清除错误dwBytesRead = min(dwBytesRead, (DWORD)ComStat.cbInQue);

if (m_hComm == INVALID_HANDLE_VALUE)

{

return false;

}

/** 临界区保护*/

EnterCriticalSection(&m_csCommunicationSync);

/*等待串口输入缓冲区的输入*/

if (!dwBytesRead)

return FALSE;

BOOL bReadStatus;

//从缓冲区读取数据。

bReadStatus = ReadFile(m_hComm, lpInBuffer, dwBytesRead, &dwBytesRead, &m_osRead);//异步读取数据。

if ((!bReadStatus))

{

/* GetLastError()返回ERROR_IO_PENDING,表示串口正在进行读操作*/

if (GetLastError() == ERROR_IO_PENDING)

{

/*表示知道对象被触发信号才返回。*/

WaitForSingleObject(m_osRead.hEvent, INFINITE);

/*当串口读操作进行完毕后,m_osRead的hEvent时间会变为有信号,清空缓冲区*/

PurgeComm(m_hComm, PURGE_TXABORT | PURGE_RXABORT |

PURGE_RXCLEAR | PURGE_RXABORT);

}

/** 离开临界区*/

LeaveCriticalSection(&m_csCommunicationSync);

return true;

}

return true;

}

Main.c

#include "SerialPort.h"

using namespace std;

int _tmain(int argc, _TCHAR* argv[])

{

CSerialPort mySerialPort;//首先将之前定义的类实例化int length = 8;//定义传输的长度

rs串口verilog代码

UART是通用异步收发器的简称,其中有一种电平规范较RS232规范,它用-3~-15V表示正逻辑,3~15V表示负逻辑,通过FPGA芯片实现RS232通信首先要解决的就是FPGA电平和RS232电平之间的矛盾,通常采用MAX3232作为物理层的电平接口,根据MAX3232提供的标准配制方式把物理电路设计好后,接下来的通信就是要实现逻辑的接收和发送…… 设计最简单的RS232通信逻辑,FPGA实现将接收到的数据会发出去,总共两个数据传输引脚,一收一发。将此通信模块分为三个部分:接收模块,波特率控制模块,发送模块。 工作原理:此模块接收MAX3232传过来的串行数据,对齐进行判断采样,校验,最后将数据流中的串行数据转换为八位并行数据,将此八位数据储存,或送给发送模块发送出去。根据RS232通信标准器串行数据分为起始位、数据位、校验位、停止位,空闲时为高电平,起始位通常为低电平,数据位通常为8位,校验位分为奇校验、偶校验等,停止位一位或两位且为高电平。FPGA接收模块对此数据进行异步接收,首先就要检测其数据传输开始标识,当然就是检测开始位,于是要有下降沿检测电路,检测到下降沿是输出一高脉冲,此电路可以用两个D触发器加上基本门电路实现,脉冲触发开始进入接收状态,输出接收状态标志位,使其为1,此标志位使能波特率控制模块输出采样脉冲,此计数脉冲触发接收模块中的计数器计数,加到相应的位就把当前的串行总线上的值赋给缓冲器,或对其判断,当计数完成11次计数后,已将8位串行数据转成并行数据到缓冲器中,且进行了校验的判断和停止位的判别,这是接收状态结束,接收状态位置0,计数器清零。对于波特率产生模块用于控制采样数据脉冲的周期,其周期就为串行数据传送一个bit所用的时间,根据此时间和时钟周期设置计数值。当接收模块完成工作时,接收状态位为0时可以触发发送模块,发送模块检测接收状态的下降沿,由此产生一高脉冲,与发送模块类似,根据波特率控制模块产生的计数脉冲将并行数据转成串行数据,并加上开始位、校验位、停止位。由此完成整个串行通信模块。 要熟悉:下降沿检测程序设计,并转串设计等。 顶层模块图如下所示: 各模块的程序如下: //本程序实现rs232通信中的串行数据接收模块 module rs232_rx( //input clk,//50M的时钟输入 rst_n,//低电平复位信号输入 rx_cnt_pluse,//采样脉冲输入,总共11个采样脉冲,一个时钟宽度的高电平 rs232_in_s,//串行数据输入,空闲时为高电平,1bit低电平作为起始位,接着8bit数据位LSB传输模式,接着偶数校验位,接着1bit低电平作为停止位

verilog串口程序

串口通信是目前比较重要的一种通信方式,主要是用于计算机和外部的通信。首先简单的介绍一下串口通信的原理: 串口用于ASCII码字符的传输。通信使用3根线完成:(1)地线,(2)发送,(3)接收。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但是不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通行的端口,这些参数必须匹配:a,波特率:这是一个衡量通信速度的参数。它表示每秒钟传送的bit的个数。例如300波特表示每秒钟发送300个bit。当我们提到时钟周期时,我们就是指波特率例如如果协议需要4800波特率,那么时钟是4800Hz。这意味着串口通信在数据线上的采样率为4800Hz。通常电话线的波特率为14400,28800和36600。波特率可以远远大于这些值,但是波特率和距离成反比。高波特率常常用于放置的很近的仪器间的通信,典型的例子就是GPIB设备的通信。b,数据位:这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据不会是8位的,标准的值是5、7和8位。如何设置取决于你想传送的信息。比如,标准的ASCII码是0~127(7位)。扩展的ASCII码是0~255(8位)。如果数据使用简单的文本(标准ASCII码),那么每个数据包使用7位数据。每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语“包”指任何通信的情况。c,停止位:用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。d,奇偶校验位:在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据

Verilog串口通讯设计

1 串口通信基本特点随着多微机系统的应用和微机网络的发展,通信功能越来越显得重要。串行通信是在一根传输线上一位一位地传送信息.这根线既作数据线又作联络线。串行通信作为一种主要的通信方式,由于所用的传输线少,并且可以借助现存的电话网进行信息传送,因此特别适合于远距离传送。在串行传输中,通信双方都按通信协议进行,所谓通信协议是指通信双方的一种约定。约定对数据格式、同步方式、传送速度、传送步骤、纠错方式以及控制字符定义等问题做出统一规定,通信双方必须共同遵守。异步起止式的祯信息格式为:每祯信息由四部分组成:a.1位起始位。b.5~8位数据位。传送顺序是低位在前,高位在后.依次传送。c.一位校验位,也可以没有。d.最后是1位或是2位停止位。FPGA(Field Pmgrammable Gate Array)现场可编程门阵列在数字电路的设计中已经被广泛使用。这种设计方式可以将以前需要多块集成芯片的电路设计到一块大模块可编程逻辑器件中,大大减少了电路板的尺寸,增强了系统的可靠性和设计的灵活性。本文详细介绍了已在实际项目中应用的基于FPGA的串口通讯设计。本设计分为硬件电路设计和软件设计两部分,最后用仿真验证了程序设计的正确性。 2 系统的硬件设计本方案的异步串行通信的硬件接口电路图如图1所示,主要由四部分组成:RS-485数据发送模块、FPGA串口模块、MAX3223和DB9。各部分功能简述如下:RS-485数据发送模块是将前续电路的数据发送到FPGA,供本电路处理,亦即本电路的输入。RS485是符合RS-485和RS-4225串口标准的低功耗半双工收发器件,有3.3V和5V两种,在本设计中选用了3.3V的器件SP3485。SP3485的内部结构示意图如图2所示在本设计中。485的7脚和8脚与前端信号相连接,用于接收输入的数据。数据格式是这样的:一帧数据有25位,报头是16个高电平和1个低电平,接下来是 8位有效的数据。传输速率为700k波特率。2脚是使能端,与FPGA的I/O口相连,由FPGA提供逻辑控制信号。1脚和4脚也与FPGA相连,由 FPGA对输入数据进行处理。 图1异步串行通信硬件接口功能框图 图2 SP3485的内部结构示意图FPGA串口模块是将由RS-485发送过来的数据进行处理,提取出8位有效数据,并按异步串口通讯的格式要求输出到MAX3223的12脚。FPGA选用Xilinx 公司的Spartan II系列xc2s50。此部分为该设计的主体。如上所述,输入数据的传输速率为700k波特率。为了使FPGA能够正确地对输入数据进行采样,提高分辨率能力和抗干扰能力,采样时钟必须选用比波特率更高的时钟,理论上至少是波特率时钟的2倍。在本设计中选用4倍于波特率的时钟,利用这种4倍于波特率的接收时钟对串行数据流进行检测和定位采样,接收器能在一个位周期内采样4次。如果没有这种倍频关系,定位采样频率和传送波特率相同,则在一个位周期中,只能采样一次,分辨率会差。比如,为了检测起始位下降沿的出现,在起始位的前夕采样一次之后,下次采样要到起始位结束前夕才进行。而假若在这个周期期间,因某种原因恰恰使接收时钟往后偏移了一点点,就会错过起始位。造成整个后面位的检测和识别错误。针对本设计,FPGA的软件共分了三个模块: 1.时钟分频模块。模块的功能是用来产生所需要的数据采集时钟和数据传输时钟。系统主频是40M的。数据采集时钟是2.8M的,发送时钟是11.2k。 2. 提取数据模块。由RS485发送过来的数据共有25位,其中只有8位是有效数据。为了发送这8位有效数据。必须先将其提取出来。提取的办法是这样的:通过连续检测到的16个高电平和一个低电平。判断8位有效数据的到来。然后按照串行数据传输的格式,在加上起始位和停止位后,将其存储于输出缓冲寄存器中。在这里,我们的串行数据输出格式是这样规定的,一位起始位,八位数据位,一位停止位,无校验位。 3.串行数据输出模块。这一模块相对比较简单,波特率选为11.2k,模块的

串口接收、发送数据OK

//接收数据 procedure TFrm_https://www.doczj.com/doc/a314275243.html,m1ReceiveData(Sender: TObject; Buffer: PAnsiChar; BufferLength: Word); var i:integer; rbuf,sbuf:array[1..21] of byte; tmpstr,tmphex,tmpview:string; begin tmpstr:=''; tmphex:=''; move(buffer^,pchar(@rbuf)^,bufferlength); for i:=1 to BufferLength do begin tmpstr:=tmpstr+char(rbuf[i]); //字符型 tmphex:=tmphex+inttohex(rbuf[i],2); //16进制型 end; if trim(tmpstr)<>'' then viewstring:=viewstring+tmpstr; if tmphex='0A' then begin //Memo1.Lines.Add(viewstring); if Edit1.Text<>viewstring then Edit1.Text:=viewstring; viewstring:=''; end; end; //发送数据 procedure senddata; var i:integer; commflg:boolean; begin viewstring:=''; commflg:=true; for i:=1 to high(sbuf) do begin if not https://www.doczj.com/doc/a314275243.html,m1.writecommdata(@sbuf[i],1) then begin commflg:=false; break; end; //发送时字节间的延时 sleep(5); viewstring:=viewstring+inttohex(sbuf[i],2)+' '; if not commflg then messagedlg('发送失败!',mterror,[mbyes],0); end; viewstring:='发送'+viewstring; Form1.memo1.lines.add(viewstring); Form1.memo1.lines.add(''); end; procedure TForm1.sentcustom(); var str11:string ; i,j,k:integer; tmpstr:string; begin if Edit1.Text<>'' then begin str11:=Trimplace(Edit1.Text); //替换字符串中的所有空格 i:=round(length(str11)/2); //获得字符串长度,除2取整后加1 setlength(sbuf,i+1); //重新设定发送数组范围 for j:=1 to i do begin tmpstr:=copy(str11,j*2-1,2); if tmpstr='' then tmpstr:='00'; sbuf[j]:=byte(strtoint('$'+tmpstr)); //将变量转换为byte数组end; end else begin sbuf[1]:=byte($53); //帧头 sbuf[2]:=byte($54); sbuf[3]:=byte($2C); sbuf[4]:=byte($47); sbuf[5]:=byte($53); sbuf[6]:=byte($2C); sbuf[7]:=byte($2B); sbuf[8]:=byte($20); sbuf[9]:=byte($20); sbuf[10]:=byte($20); sbuf[11]:=byte($30); sbuf[12]:=byte($2E); sbuf[13]:=byte($30); sbuf[14]:=byte($30); sbuf[15]:=byte($20); sbuf[16]:=byte($6B); sbuf[17]:=byte($67); sbuf[18]:=byte($20); sbuf[19]:=byte($20); sbuf[20]:=byte($0D); sbuf[21]:=byte($0A); end; end;

FPGA模拟串口自收发-Verilog

实现功能,FPGA里实现从PC串口接收数据,接着把接收到的数据发回去。波特率可选9600bps,可调1bit起始位,8bit数据,1bit停止位,无校验位。 参考《VHDL硬件描述语言与和数字逻辑电路设计》 模块介绍如下 一、串口数据接收模块:特别注意一个数据位占4个clk_bps_4时钟周期。 串口数据接收控制 当数据接收端rxd出现起始位低电平,启动接收控制计数器rx_cnt,置位为8’b0111_00(28), 即rx_cnt[5:2]== 4’b0111(7),rx_cnt*1:0+ == 2'b00(0);一个计数周期开始,伴随clk_bps_4, rx_cnt加1(每一个数据位加4) 串口接收数据移位控制(关键采样点的选取) 每当rx_cnt[1:0] == 2'b01,为了保证在rxd一位数据靠近中间位置采样;每4个clk_bps_4, rx_cnt[5:2]加1当rx_cnt[5:2] == 8,9,10….15,完成8位的数据采样,串并变换 置位标志位rxdF数据接收标志 rxd出现起始位低电平, rxdF置1,表示数据接收开始;当rx_cnt计数到8’b1111_11(63),数据接收完成,rxdF置0 置位标志位rdFULL;//接收锁存器满标志 空闲时rdFULL置0,当数据接收完成,数据锁存到do_latch,同时rdFULL置1,向上层模块表示数据以准备OK,可以来读取;rd置0,表示上层模块开始读取数据,rdFULL置0,表示数据已读走 二、串口数据发送模块:数据发送依赖于wr(低电平有效) 空闲时wr置1,数据发送时wr产生低电平脉冲,wr上升沿将数据锁存到din_latch; 串口数据发送控制: wr由0跳变为1后,启动发送控制计数器tx_cnt,置位为8’b0111_00(28), 即tx_cnt[5:2]== 4’b0111(7),tx_cnt[1:0] == 2'b00(0);一个计数周期开始,伴随clk_bps_4, tx_cnt加1(每一个数据位加4)

使用串口UART0接收上位机发送的数据

/****************************************Copyright (c)************************************************** ** Guangzou ZLG-MCU Development Co.,LTD. ** graduate school ** https://www.doczj.com/doc/a314275243.html, ** **--------------File Info------------------------------------------------------------------------------- ** File name: main.c ** Last modified Date: 2004-09-16 ** Last Version: 1.0 ** Descriptions: The main() function example template ** **------------------------------------------------------------------------------------------------------ ** Created by: Chenmingji ** Created date: 2004-09-16 ** Version: 1.0 ** Descriptions: The original version ** **------------------------------------------------------------------------------------------------------ ** Modified by: ** Modified date: ** Version: ** Descriptions: ** ***************************************************************** ***************************************/ /**************************************************************** ************ * 文件名:main.C * 功能:使用串口UART0接收上位机发送的数据,并将数据原封不动地发送回上位机。 * 说明:通讯波特率115200,8位数据位,1位停止位,无奇偶校验。 ***************************************************************** ***********/

基于verilog的串口通信实验指导和源程序

自己看了很多材料以后,精心整理的串口通信实验原理和指导,在网上找了很多代码,大部分因为没有很好的注释,看起来很头疼,于是自己写了一份,附带详细的注释,在modelsim仿真器上已经得到验证,现在传上来,仅供参考。 PS1:最后部分给出了一个测试文件,写的非常简单,只是验证了功能,不是很好的测试; PS2:代码部分看上去有点乱,因为在word中代码的层次结构无法清晰显示,如有需要,下载后把代码copy到notepad++这种类似的专用变成工具里面,就很清晰的显示代码和注释了。 第一部分:实验原理串行通信要求的传输线少,可靠性高,传输距离远,被广泛应用于计算机和外设的数据交换。通常都由通用异步收发器(UART)来实现串口通信的功能。在实际应用中,往往只需要UART的几个主要功能,专用的接口芯片会造成资源浪费和成本提高。随着FPGA/CPLD的飞速发展与其在现代电子设计中的广泛应用,FPGA/CPLD功能强大、开发过程投资小、周期短、可反复编程、保密性好等特点也越来越明显。因此可以充分利用其资源,在芯片上集成UART功能模块,从而简化了电路、缩小了体积、提高了可靠性,而且设计时的灵活性更大,周期更短。

UART简介 UART(Universal Asynchronous Receiver Transmitter通用异步收发器)是一种应用广泛的短距离串行传输接口。常常用于短距离、低速、低成本的通讯中。8250、8251、NS16450等芯片都是常见的UART器件。 基本的UART通信只需要两条信号线(RXD、TXD)就可以完成数据的相互通信,接收与发送是全双工形式。TXD是UART发送端,为输出;RXD是UART接收端,为输入。 UART的基本特点是: (1)在信号线上共有两种状态,可分别用逻辑1(高电平)和逻辑0(低电平)来区分。在发送器空闲时,数据线应该保持在逻辑高电平状态。 (2)起始位(Start Bit):发送器是通过发送起始位而开始一个字符传送,起始位使数据线处于逻辑0状态,提示接受器数据传输即将开始。 (3)数据位(Data Bits):起始位之后就是传送数据位。数据位一般为8位一个字节的数据(也有6位、7位的情况),低位(LSB)在前,高位(MSB)在后。 (4)校验位(parity Bit):可以认为是一个特殊的数据位。校验位一般用来判断接收的数据位有无错误,一般是奇偶校验。在使用中,该位常常取消。 (5)停止位:停止位在最后,用以标志一个字符传送的结束,它对应于逻辑1状态。 (6)位时间:即每个位的时间宽度。起始位、数据位、校验位的位宽度是一致的,停止位有0.5位、1位、1.5位格式,一般为1位。 (7)帧:从起始位开始到停止位结束的时间间隔称之为一帧。

串口通信接收发送数据显示

1、接收数据 #include #define Data_d P0 #define Data_w P2 #define uint unsigned int #define uchar unsigned char unsigned char flag; unsigned char Duanma[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88};// 显示段码值01234567 code const unsigned char Weima[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//分别对应相应的数码管点亮,即位码 /*------------------------------------------------ 延时子程序 ------------------------------------------------*/ void delayms(unsigned int z) { unsigned int x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } ///*------------------------------------------------ // 定时器初始化子程序 //------------------------------------------------*/ //void Init_Timer0(void) //{ // TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响 // //TH0=0x00; //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出 // //TL0=0x00; // EA=1; //总中断打开 // ET0=1; //定时器中断打开 // TR0=1; //定时器开关打开 //} /*----------------------------------------------- 串口初始化 ------------------------------------------------*/ void serial_init(void) { SCON = 0x50; /* SCON: 模式1, 8-bit UART, 使能接收REN=1,SM0=0,SM1=1 */ TMOD |= 0x20; /* TMOD: timer 1, mode 2, 8-bit reload */

Verilog实现串口接收多帧数据

`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 19:50:45 04/19/2015 // Design Name: // Module Name: Serial_Decoder // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module Serial_Decoder( input wire clk_seri, //串口时钟,用于从串口发送命令给FPGA input wire rst, input wire RxD, output reg[1:0] modu_sel, //BPSK,QPSK,8PSK选择 output reg[13:0] ser_asf, //由串口发过来的asf output reg[31:0] ser_ftw, //由串口发过来的ftw output reg cmd_done, //上位机给FPGA发送指令结束 output reg[31:0] dina, //ROM存储器,用于存储外部PN码 output reg wea, output reg[1:0] addra ); reg cmd_rdy;//指令接收完成 reg [3:0] instr_code;//用于分辨命令,是asf还是ftw还是外部PN码 reg [31:0] cmd_data; //接收从上层发过来的命令 wire RxD_data_ready;

串口通讯设计之Verilog实现

串口通讯设计之 V e r i l o g实现 Revised as of 23 November 2020

串口通讯设计之V e r i l o g实现 FPGA串口模块是将由RS-485发送过来的数据进行处理,提取出8位有效数据,并按异步串口通讯的格式要求输出到MAX3223的12脚。FPGA选用Xilinx公司的SpartanII系列xc2s50。此部分为该设计的主体。如上所述,输入数据的传输速率为700k波特率。为了使FPGA能够正确地对输入数据进行采样,提高分辨率能力和抗干扰能力,采样时钟必须选用比波特率更高的时钟,理论上至少是波特率时钟的2倍。 1 串口通信基本特点随着多微机系统的应用和微机网络的发展,通信功能越来越显得重要。串行通信是在一根传输线上一位一位地传送信息.这根线既作数据线又作联络线。串行通信作为一种主要的通信方式,由于所用的传输线少,并且可以借助现存的电话网进行信息传送,因此特别适合于远距离传送。在串行传输中,通信双方都按通信协议进行,所谓通信协议是指通信双方的一种约定。约定对数据格式、同步方式、传送速度、传送步骤、纠错方式以及控制字符定义等问题做出统一规定,通信双方必须共同遵守。异步起止式的祯信息格式为:每祯信息由四部分组成: 位起始位。 ~8位数据位。传送顺序是低位在前,高位在后.依次传送。c.一位校验位,也可以没有。d.最后是1位或是2位停止位。 FPGA(Field Pmgrammable Gate Array)现场可编程门阵列在数字电路的设计中已经被广泛使用。这种设计方式可以将以前需要多块集成芯片的电路设计到一块大模块可编程逻辑器件中,大大减少了电路板的尺寸,增强了系统的可靠性和设计的灵活性。本文详细介绍了已在实际项目中应用的基于FPGA的串口通讯设计。 本设计分为硬件电路设计和软件设计两部分,最后用仿真验证了程序设计的正确性。 2 系统的硬件设计 本方案的异步串行通信的硬件接口电路图如图1所示,主要由四部分组成:RS-485数据发送模块、FPGA 串口模块、MAX3223和DB9。各部分功能简述如下: RS-485数据发送模块是将前续电路的数据发送到FPGA,供本电路处理,亦即本电路的输入。RS485是符合RS-485和RS-4225串口标准的低功耗半双工收发器件,有和5V两种,在本设计中选用了的器件SP3485。 在本设计中。485的7脚和8脚与前端信号相连接,用于接收输入的数据。数据格式是这样的:一帧数据有25位,报头是16个高电平和1个低电平,接下来是 8位有效的数据。传输速率为700k波特率。2脚是使能端,与FPGA的I/O口相连,由FPGA提供逻辑控制信号。1脚和4脚也与FPGA相连,由 FPGA对输入数据进行处理。 FPGA串口模块是将由RS-485发送过来的数据进行处理,提取出8位有效数据,并按异步串口通讯的格式要求输出到MAX3223的12脚。FPGA选用Xilinx公司的Spartan II系列xc2s50。此部分为该设计的主体。如上所述,输入数据的传输速率为700k波特率。为了使FPGA能够正确地对输入数据进行采样,提高分辨率能力和抗干扰能力,采样时钟必须选用比波特率更高的时钟,理论上至少是波特率时钟的2倍。在本设计中选用4倍于波特率的时钟,利用这种4倍于波特率的接收时钟对串行数据流进行检测和定位采样,接收器能在一个位周期内采样4次。如果没有这种倍频关系,定位采样频率和传送波特率相同,则在一个位周期中,只能采样一次,分辨率会差。比如,为了检测起始位下降沿的出现,在起始位的前夕采样一次之后,下次采样要到起始位结束前夕才进行。而假若在

Verilog程序6、UART(串口通信)

这个程序没有仿真、没有测试。。 1 UART功能设计 1.1 UART的工作原理 异步通信时,UART发送/接收数据的传输格式如图1所示,一个字符单位由开始位、数据位、停止位组成。 异步通信的一帧传输经历以下步骤: (1)无传输。发送方连续发送信号,处于信息“1”状态。 (2)起始传输。发送方在任何时刻将传号变成空号,即“1”跳变到“O”,并持续1位时间表明发送方开始传输数据。而同时,接收方收到空号后,开始与发送方同步,并期望收到随后的数据。 (3)奇偶传输。数据传输之后是可供选择的奇偶位发送或接收。 (4)停止传输。最后是发送或接收的停止位,其状态恒为“1”。 其程序的结构框图如下: 该程序的效果是串口接受到从计算机发送过来的数据后,又把数据发回给计算机,串口通信是串行的。 其uart.v为顶层文件,包含其他模块,speed_select.v文件的作用为为uart_rx.v和uart_tx.v 设置波特率。

uart.v(顶层文件) `timescale 1ns / 1ps ///////////////////////////////////////////////////////////////////// ///////////// // Company: // Engineer: // // Create Date: 16:08:27 11/12/2010 // Design Name: // Module Name: uart // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ///////////////////////////////////////////////////////////////////// ///////////// module uart(clk,rst_n,rs232_rx,rs232_tx); input clk,rst_n,rs232_rx; output rs232_tx; wire bps_start1,bps_start2,clk_bps1,clk_bps2,rx_int; wire [7:0] rx_data; //发送模块的时钟 speed_select speed_tx ( .clk(clk), .rst_n(rst_n), .bps_start(bps_start2), .clk_bps(clk_bps1) ); //接受模块的时钟 speed_select speed_rx ( .clk(clk), .rst_n(rst_n), .bps_start(bps_start2), .clk_bps(clk_bps2)

verilog编写的uart程序

// UART_FPGA.v 顶层模块,实现由ARM控制FPGA读取串口数据,经过ARM返回给FPGA串口发送出去; `timescale 1ns/1ns module UART_FPGA( //EMIF PIN input wire [10:0] EADDR_pin /* synthesis syn_noclockbuf = 1 */, inout wire [15:0] EDATA_pin , input wire EnOE_pin /* synthesis syn_noclockbuf = 1 */, input wire EnWE_pin /* synthesis syn_noclockbuf = 1 */, input wire EnGCS1_pin /* synthesis syn_noclockbuf = 1 */, output wire EINT2_pin , //LED_run output wire LED_run_pin , //UART output wire UART_TXD0 , input wire UART_RXD0 /* synthesis syn_noclockbuf = 1 */, //test signal output wire TXD_test, output wire RXD_test, output reg TXD_start, output wire EINT2_test, output wire TXD_over_test, output wire uart_send_WR, //FPGA SYSTEM PIN input wire nRESET_pin /* synthesis syn_noclockbuf = 1 */, input wire CLK_50M_pin ); wire [15:0] write_data;

Verilog编写的RS232(Uart)程序

module my_uart_top( clk,rst_n, rs232_rx,rs232_tx ); input clk; lk(clk), st_n(rst_n), .bps_start(bps_start1), .clk_bps(clk_bps1) , ); my_uart_rx my_uart_rx( .clk(clk), st_n(rst_n), .rs232_rx(rs232_rx), .rx_data(rx_data), .rx_int(rx_int), .clk_bps(clk_bps1), % .bps_start(bps_start1) ); lk(clk), st_n(rst_n), .bps_start(bps_start2), .clk_bps(clk_bps2) ); ` my_uart_tx my_uart_tx( .clk(clk), st_n(rst_n), .rx_data(rx_data), .rx_int(rx_int), .rs232_tx(rs232_tx), .clk_bps(clk_bps2), .bps_start(bps_start2) ); . endmodule module my_uart_rx( clk,rst_n, rs232_rx,rx_data,rx_int, …

clk_bps,bps_start ); input clk; // 50MHz主时钟 input rst_n; //低电平复位信号 input rs232_rx; // RS232接收数据信号 input clk_bps; // clk_bps的高电平为接收或者发送数据位的中间采样点 output bps_start; //接收到数据后,波特率时钟启动信号置位 ` output[7:0] rx_data; //接收数据寄存器,保存直至下一个数据来到 output rx_int; //接收数据中断信号,接收到数据期间始终为高电平 //---------------------------------------------------------------- reg rs232_rx0,rs232_rx1,rs232_rx2,rs232_rx3; //接收数据寄存器,滤波用 wire neg_rs232_rx; //表示数据线接收到下降沿 always @ (posedge clk or negedge rst_n) begin { if(!rst_n) begin rs232_rx0 <= 1'b0; rs232_rx1 <= 1'b0; rs232_rx2 <= 1'b0; rs232_rx3 <= 1'b0; end else begin rs232_rx0 <= rs232_rx; : rs232_rx1 <= rs232_rx0; rs232_rx2 <= rs232_rx1; rs232_rx3 <= rs232_rx2; end end //下面的下降沿检测可以滤掉<20ns-40ns的毛刺(包括高脉冲和低脉冲毛刺), //这里就是用资源换稳定(前提是我们对时间要求不是那么苛刻,因为输入信号打了好几拍) //(当然我们的有效低脉冲信号肯定是远远大于40ns的) , assign neg_rs232_rx = rs232_rx3 & rs232_rx2 & ~rs232_rx1 & ~rs232_rx0; //接收到下降沿后neg_rs232_rx置高一个时钟周期 //---------------------------------------------------------------- reg bps_start_r; reg[3:0] num; //移位次数 reg rx_int; //接收数据中断信号,接收到数据期间始终为高电平

verilog串口收发

1.//UART串行口模块,波特率9600bps 2.//陈鹏 3.//20110118 4. 5.module UART ( 6. sys_clk,//系统时钟输入 7. reset_n,//异步复位输入 8. Rx,//数据输入引脚 9. NewRxData,//接收到新数据 10. RxDATA//RxDATA当前接收的数据 11. ); 12. 13. input sys_clk,reset_n,Rx; 14. output NewRxData; 15. output [7 : 0] RxDATA; 16. reg [7 : 0] RxDATA; 17. 18. parameter SYS_CLK = 20000000;//系统时钟 19. parameter Rx_CLK = 9600;//9600bps 20. parameter RxDATA_W = 12;//波特率时钟发生器分频寄存器位宽 21. parameter RXCLK_DATA = SYS_CLK / Rx_CLK - 1;//波特率分频器时钟分频 值 (2083) 22. 23. 24. //波特率时钟发生器 25. reg [RxDATA_W-1 : 0] clk_cnt; 26. reg EN_RXCLK;//使能接收时钟 27. wire RX_CLK;//接收波特率时钟 28. always @ (posedge sys_clk or negedge reset_n) 29. if(!reset_n) 30. clk_cnt <= 12'd0; 31. else if(!EN_RXCLK)//不需要使能时钟 32. clk_cnt <= 12'd0; 33. else if(clk_cnt == RXCLK_DATA) 34. clk_cnt <= 12'd0; 35. else 36. clk_cnt <= clk_cnt + 1'b1; 37. 38. assign RX_CLK = (clk_cnt == RXCLK_DATA/2);//产生接收时钟 39. 40. 41. //接收数据线下降沿检测,用来启动数据接收 42. //采用边沿检测法,因为数据线空闲位高,起始位位低,因此1帧数据开始有一个下降沿 43. reg RxThis,RxLast;

ADDA等一些芯片的verilog程序

/* AD0809 module v1.0 work up to 5M sample = 25us 40khz for normal clk = 2.5M sample = 30us 33khz */ module ad0809( clkin, adclk, eoc, st, ale, datain, oe, dataout ); input clkin; input eoc; input [7:0]datain; output st; output ale; output oe; output adclk; output [7:0]dataout; reg adclk; reg [7:0]dataout; reg st; reg oe; reg ale; //frequence divider for AD parameter Div_adclk = 8'd9;//(9+1)*2=20 adclk=2.5M parameter Div_clk_state = 4'd4;//(4+1)*2=10 clk_state=5M

reg [8:0]div_cnt_ad;//frequence div cnt reg [3:0]div_cnt_state; reg clk_state; always@(negedge clkin)begin if(div_cnt_ad != Div_adclk) div_cnt_ad <= div_cnt_ad + 1'b1; else begin div_cnt_ad <= 0; adclk <= ~adclk; end if(div_cnt_state != Div_clk_state) div_cnt_state <= div_cnt_state + 1'b1; else begin div_cnt_state <= 0; clk_state <= ~clk_state; end end /*AD convert*/ reg [3:0]state; reg [7:0]delay; initial begin state <= 4'd0; end always@(negedge clk_state)begin case(state) 4'd0:begin //clear all st <= 1'b0; oe <= 1'b0; ale <= 1'b0;

相关主题
文本预览
相关文档 最新文档