ATMEGA16(L)的USART与PC机串行通信
PC机与AVR单片机之间串行通信的实现

程序清单 PC 通信 (B IO S 调用)
# include " stdio 1h" # include "b io s1h" un signed cha r inbuf[ 100 ]= {0}, 3 in tp , 3 inep; un signed cha r ou tbuf [ 100 ]= {0}, 3 ou ttp , 3 ou tep;
7
线路
6
线路信号被检测
5
振铃指示
4
数据装置就绪
3
清除发送
2
线路信号变化
1
脉冲后沿振铃检测
0
清除发送信号变化
B IO S 功能调用, 主要用查询 COM 口状态来进行读 写; 如果发送寄存器空, 即可进行下次发送, 通过查询发现 传送有错误, 通知 PC 机重新发送; 如果接收数据就绪, 就 可以读入数பைடு நூலகம், 通过查询发现有错误, 就通知发送端重发。
AV R 单片机是 1997 年开始由美国 A TM EL 公司逐 步设计的一个单片机系列, 几十个品种, 其特点是速度快, 每秒可执行 16 M 条指令; 功能强, 片内集成了 FLA SH 作 程序存储器、SRAM , E2PROM , 几个定时器 计时器、多 个 I O 口、A D 转换器、PWM 脉宽调制器 (可用作D A 转换器)、异步串行口、SP I 同步串行口等。特别是近一两 年推出的M ega16 到M ega128 等型号单片机片内带有 I2C 总线接口, J TA G 接口 (支持在线仿真调试) 和A D 转换 器带有×10、×200 的差动放大器可直接转换 mV 级模拟
基于ATmega16单片机的USART串口通信测试程序

基于ATmega16单片机的USART串口通信测试程序/************************************************************** *************** 编译环境:ICC AVR。
文件名:基于ATmega16单片机的USART串口通信测试程序功能:利用ATmega16的USART,从TXD异步串出数据,将TXD 与RXD短接,从RXD输入,通过PC口送到一个LED数码管显示,实现了自发自收的过程?作者:赵国朋班级:鹏程001时间:2013年04月5日修改:无备住:一.硬件接口电路描述1.晶振:8MHz2.MCU的PC口与共阴极数码管相接3.TXD与RXD相接TXD --- RXD/************************************************************** ***************/ #include //包含单片机型号头文件#include //包含"位操作"头文件#define uchar unsigned char //宏定义#define uint unsigned int#define ulong unsigned long#define BAUD 9600 //波特率采用9600b/s#define CRYSTAL 8000000 //系统时钟为8MHz//计算和定义波特率设置参数#define BAUD_SETTING (uint)((ulong)CRYSTAL/(16*(ulong)BAUD)-1)#define BAUD_H (uchar)(BAUD_SETTING>>8)#define BAUD_L (uchar)(BAUD_SETTING)//USART控制和状态寄存器的标志位定义#define FRAMING_ERROR (1<<fe)< bdsfid="122" p=""></fe)<>#define PARITY_ERROR (1<<pe)< bdsfid="124" p=""></pe)<>#define DATA_OVERRUN (1<<dor)< bdsfid="126" p=""></dor)<>#define DATA_REGISTER_EMPTY (1<<udre)< bdsfid="128" p=""></udre)<>#pragma interrupt_handler USART_Rx_Isr:12 //USART接收中断服务#pragma data:dataflash Duan_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d, 0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};// 显示段码值0~F /************ MCU初始化函数**************//************************************************************** **************** 函数名:MCU_Init()功能:MCU初始化参数:无返回值:无/************************************************************** **************** /void MCU_Init(){PORTC=0X00;DDRC=0XFF;PORTD=0X03;DDRD=0X02;}/************ USART初始化函数**************//************************************************************** **************** 函数名:USART_Init()功能:USART初始化参数:无返回值:无/************************************************************** **************** /void USART_Init(){// DDRD=0X02;//PORTD=0X03;UCSRA=0X00;UCSRB=(1<<rxcie)|(1<<rxen)|(1<<=""></rxcie)|(1<<rxen)|( 1<//UCSRB=0X98;UCSRC=(1<<ursel)|(1<<ucsz1)|(1<<="" bdsfid="161" p=""></ursel)|(1<<ucsz1)|(1<//UCSRC=0X86UBRRH=BAUD_H;UBRRL=BAUD_L;}/************ USART中断服务函数**************//************************************************************** **************** 函数名:USART_Rx_Isr()功能:USART中断服务,将欲显示的数码送到I/O寄存器参数:无返回值:无/************************************************************** **************** /void USART_Rx_Isr(){uchar status,data;//DDRC=0XFF;status=UCSRA;data=UDR;if((status&(FRAMING_ERROR|PARITY_ERROR|DATA_OVERRU N))==0)PORTC=Duan_table[data];}/************ USART发送数据函数**************//************************************************************** **************** 函数名:USART_Transmit()功能:将要发送的数据送到USART缓冲区UDR中参数:uchar data返回值:无/************************************************************** **************** /void USART_Transmit(uchar data)while(!(UCSRA&DATA_REGISTER_EMPTY));UDR=data;}/************ 延时函数**************//************************************************************** **************** 函数名:Delay_Us()、Delay_Ms()功能:微秒级、毫秒级延时参数:Us --- 欲延时的us数Ms --- 欲延时的ms数返回值:无/****************************************************************************** /void Delay_Us(uint Us){uint i;Us=Us*5/4; //5/4是在8MHz晶振下,通过软件仿真反复实验得到的数值for( i=0;i<us;i++);< bdsfid="203" p=""></us;i++);<>}void Delay_Ms(uint Ms){uint i,j;for( i=0;i<ms;i++)< bdsfid="209" p=""></ms;i++)<>for(j=0;j<1141;j++);//1141是在8MHz晶振下,通过软件仿真反复实验得到的数值}/************ 主函数**************//************************************************************** **************** 函数名:main()功能:参数:无返回值:无/************************************************************** **************** /void main()uchar i=0;//定义变量MCU_Init();USART_Init();SREG=BIT(7);//开全局中断while(1){for(i=0;i<16;i++) {USART_Transmit(i); Delay_Ms(500);}}}。
PC机与单片机间串行通信优化控制方法

PC机与单片机间串行通信优化控制方法现如今,随着信息与通信技术的飞速发展,计算机已经成为人们日常生活和工作中不可或缺的工具之一。
而在计算机的应用中,PC机与单片机之间的串行通信显得尤为重要。
本文将探讨PC机与单片机之间串行通信的优化控制方法,旨在提高通信的效率与稳定性。
一、概述串行通信是指数据在两个设备之间的传输通过一个信道以位的形式进行,其中最常见的串行通信协议是UART (Universal Asynchronous Receiver Transmitter)。
在PC机与单片机之间的串行通信中,UART协议常用于数据的发送与接收。
本文将针对UART协议展开优化控制方法的讨论。
二、波特率设置波特率是指在串行通信中每秒钟传送的比特数,波特率的设置直接影响着通信的速度。
为了提高通信的效率,PC机与单片机之间的波特率设置应合理选择。
通常情况下,波特率越高,传输速度越快,但也存在着传输错误率高的问题。
因此,在实际应用中人们需要在速度和准确性之间做出权衡。
可以通过对比不同波特率下的传输速度和错误率,选择一个合适的波特率。
三、帧结构优化帧结构是指在串行通信中,数据传输的最小单元。
为了保证数据的可靠传输和正确解析,帧结构的优化非常重要。
在PC机与单片机的串行通信中,帧结构主要包括起始位、数据位、校验位和停止位。
可以采用以下方式对帧结构进行优化:1. 起始位:通过设置适当的起始位,可以使接收端正确接收到数据的开始位置。
2. 数据位:根据实际通信数据的位数,选择合适数目的数据位。
不要超过通信协议规定的最大位数,也不要过少。
3. 校验位:校验位的设置有助于检验数据传输的准确性。
常见的校验方式包括奇偶校验、奇校验和偶校验等。
可以根据实际需求选择合适的校验位。
4. 停止位:停止位的设置用于标识数据传输的结束位置。
在确定起始位和数据位之后,需要明确停止位的个数。
通过对帧结构的优化设置,可以提高串行通信的可靠性和稳定性。
Atmega16单片机介绍

Atmega16单片机介绍ATmega16是基于增强的AVR RISC结构的低功耗8 位CMOS微控制器。
由于其先进的指令集以及单时钟周期指令执行时间,ATmega16 的数据吞吐率高达1 MIPS/MHz,从而可以缓减系统在功耗和处理速度之间的矛盾。
ATmega16 AVR 核具有丰富的指令集和32 个通用工作寄存器。
所有的寄存器都直接与算逻单元(ALU) 相连接,使得一条指令可以在一个时钟周期同时访问两个独立的寄存器。
这种结构大大提高了代码效率,并且具有比普通的CISC 微控制器最高至10 倍的数据吞吐率。
ATmega16 有如下特点:16K字节的系统可编程Flash(具有同时读写的能力,即RWW),512字节EEPROM,1K 字节SRAM,32 个通用I/O 口线,32 个通用工作寄存器,用于边界扫描的JTAG 接口,支持片调试与编程,三个具有比较模式的灵活的定时器/ 计数器(T/C),片/外中断,可编程串行USART,有起始条件检测器的通用串行接口,8路10位具有可选差分输入级可编程增益(TQFP 封装) 的ADC ,具有片振荡器的可编程看门狗定时器,一个SPI 串行端口,以及六个可以通过软件进行选择的省电模式。
工作于空闲模式时CPU 停止工作,而USART、两线接口、A/D 转换器、SRAM、T/C、SPI 端口以及中断系统继续工作;掉电模式时晶体振荡器停止振荡,所有功能除了中断和硬件复位之外都停止工作;在省电模式下,异步定时器继续运行,允许用户保持一个时间基准,而其余功能模块处于休眠状态; ADC 噪声抑制模式时终止CPU 和除了异步定时器与ADC 以外所有I /O 模块的工作,以降低ADC 转换时的开关噪声; Standby 模式下只有晶体或谐振振荡器运行,其余功能模块处于休眠状态,使得器件只消耗极少的电流,同时具有快速启动能力;扩展Standby 模式下则允许振荡器和异步定时器继续工作。
ATMEGA16单片机与MCGS通信(MODBUS-RTU协议)

#include <avr/io.h>#include <avr/interrupt.h>#include <util/delay.h>#include "ds18b20.h"#define uchar unsigned char#define uint unsigned intvolatile uchar reve_data,renum=0,mend=0,nend=0,a1=1,a2=1,a3=1,a4=1,a5=1,a6=1,a7=1,a8=1,a9=1; void INT_Init();#define BAUD 38400 //波特率38.4kbp/svolatile uchar rx[7]={0x01,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00};uchar tx[30];volatile uchar crcl=0x00,crch=0x00;uchar led=0xff;//发送字符void send_char( uchar data ){/* 等待发送缓冲器为空 */while ( !( UCSRA & (1<<UDRE)) );/* 将数据放入缓冲器,发送数据 */UDR = data;}void inti_port(){DDRB=0xff;PORTB=0xff;DDRC=0xff;PORTC=0x00;}//CRC效验,将结果存储到CRCok变量中。
checkcrc(uchar *q,uchar nend){uint wcrc=0xffff;int j=0,i=0;for(i=0;i<nend;i++){wcrc ^= *q++;for(j=0;j<8;j++){if(wcrc&1){wcrc>>=1;wcrc ^= 0xa001;}else{wcrc>>=1;}}}crcl = wcrc;crch = wcrc>>8;}int main(void){inti_uart();inti_port();INT_Init();sei();while(1){gettemp();_delay_ms(1050);}}SIGNAL(SIG_UART_RECV){rx[renum++]=UDR;if(renum==8){renum=0;switch(rx[1]){case 0x01:if(!rx[3]){tx[0]=rx[0];//leD灯tx[1]=rx[1];tx[2]=0x01;DDRB=0X00;tx[3]=PORTB;DDRB=0XFF;checkcrc(tx,4);tx[4]=crcl;tx[5]=crch;send_string(tx,6);break;}else{tx[0]=rx[0];//继电器和蜂鸣器tx[1]=rx[1];tx[2]=0x01;DDRC=0X00;tx[3]=PORTC;tx[3]>>=7;DDRC=0XFF;checkcrc(tx,4);tx[4]=crcl;tx[5]=crch;send_string(tx,6);break;}case 0x04:tx[0]=rx[0];tx[1]=rx[1];tx[2]=rx[5]<<1;tx[3]=0x00;tx[4]=teml;tx[5]=0x00;tx[6]=temh;checkcrc(tx,nend=tx[2]+3);tx[tx[2]+3]=crcl;tx[tx[2]+4]=crch;send_string(tx,mend=tx[2]+5);break;case 0x05:DDRB=0XFF;switch(rx[3]){case 0x00:if(!rx[4])PORTB &= ~(1<<PB0);elsePORTB |= (1<<PB0);break;case 0x01:if(!rx[4])PORTB &= ~(1<<PB1);elsePORTB |= (1<<PB1);break;case 0x02:if(!rx[4])PORTB &= ~(1<<PB2);elsePORTB |= (1<<PB2);break;case 0x03:if(!rx[4])PORTB &= ~(1<<PB3);elsePORTB |= (1<<PB3);break;case 0x04:if(!rx[4])PORTB &= ~(1<<PB4);elsePORTB |= (1<<PB4);break;case 0x05:if(!rx[4])PORTB &= ~(1<<PB5);elsePORTB |= (1<<PB5);break;case 0x06:if(!rx[4])PORTB &= ~(1<<PB6);elsePORTB |= (1<<PB6);break;case 0x07:if(!rx[4])PORTB &= ~(1<<PB7);elsePORTB |= (1<<PB7);break;case 0x08:if(rx[4])PORTC |= (1<<PC7);elsePORTC &= ~(1<<PC7);break;}send_string(rx,8);break;default : break;}}}//*****************************红外线接收**********************************************////外部中断初始化void INT_Init(void){MCUCR |= _BV(ISC01); //选择外部中断0,下降沿触发中断MCUCR &= ~_BV(ISC00); //10:INT0的下降沿产生异步中断请求GICR |= (1 << INT0); //使能外部中断请求0DDRD &= ~_BV(PD2); //设置为输入,PORTD |= _BV(PD2); //使能上拉电阻}SIGNAL(SIG_INTERRUPT0){cli();uchar i,j,k = 0,addr[4] = {0};renum=0;GICR &= ~(1 << INT0); //禁止外部中断INT0 关闭外部中断,开始接受数据 for(i = 0;i < 14;i++){_delay_us(400);if(PIND & (1 << PD2)) //9MS内有高电平,则判断为干扰,退出处理程序 {GICR |= (1 << INT0); //使能外部中断INT0return;}}while(!(PIND & (1 << PD2))); //等待9ms低电平过去for(i = 0;i < 4;i++) //{for(j = 0;j < 8;j++)//{while(PIND & (1 << PD2)); //等待4.5ms高电平过去while(!(PIND & (1 << PD2))); //等待变高电平while(PIND & (1 << PD2))//计算高电平时间{_delay_us(100);k++;if(k >= 30) //高电平时间过长,则退出处理程序{GICR |= (1 << INT0); //使能外部中断INT0return; //}}addr[i] = addr[i] >> 1; //接受一位数据if(k >= 8){addr[i] = addr[i] | 0x80; //高电平时间大于0.56,则为数据1 }k = 0; //计时清零}}switch(addr[3]){DDRB=0XFF;case 0x07: if(a1){PORTB &= ~(1<<PB0);a1=0;}else{PORTB |= (1<<PB0);a1=1;}break;//1case 0x0b: if(a2){PORTB &= ~(1<<PB1);a2=0;}else{PORTB |= (1<<PB1);a2=1;}break;//2case 0x0f: if(a3){PORTB &= ~(1<<PB2);a3=0;}else{PORTB |= (1<<PB2);a3=1;}break;//3case 0x13: if(a4){PORTB &= ~(1<<PB3);a4=0;}else{PORTB |= (1<<PB3);a4=1;}break;//4case 0x17: if(a5){PORTB &= ~(1<<PB4);a5=0;}else{PORTB |= (1<<PB4);a5=1;}break;//5case 0x1b: if(a6){PORTB &= ~(1<<PB5);a6=0;}else{PORTB |= (1<<PB5);a6=1;}break;//6case 0x1f: if(a7){PORTB &= ~(1<<PB6);a7=0;}else{PORTB |= (1<<PB6);a7=1;}break;//7case 0x23: if(a8){PORTB &= ~(1<<PB7);a8=0;}else{PORTB |= (1<<PB7);a8=1;}break;//8case 0x03: if(a9)//蜂鸣器和继电器{PORTC |= (1<<PC7);a9=0;}else{PORTC &= ~(1<<PC7);a9=1;}break;//8case 0x27: PORTB=0X00;break;//9case 0x2b: PORTB=0XFF;break;//空格*/ default : break;}GICR |= (1 << INT0); //使能外部中断INT0sei();}#ifndef __ds18b20__H#define __ds18b20__H#include <avr/io.h>#include <util/delay.h>#include <avr/interrupt.h>#define uchar unsigned char#define uint unsigned int#define CLR_DIR_1WIRE DDRC &= ~(1<<PC6)//不再变化#define SET_DIR_1WIRE DDRC |= (1<<PC6) //IO改为输入口,高阻态,外部上拉电阻拉高#define SET_OP_1WIRE PORTC|= (1<<PC6) //改为输出口,输出低电平#define CLR_OP_1WIRE PORTC &=~(1<<PC6)#define CHECK_IP_1WIRE ( PINC & 0x40)void init_1820(void);void write_1820(unsigned char x);unsigned char read_1820(void);void gettemp(void);volatile uint Temperature;volatile unsigned char temh,teml;volatile uchar Num[4];void init_1820(void){SET_DIR_1WIRE; //设置PA0 为输出 SET_OP_1WIRE; //输出1CLR_OP_1WIRE; //输出0_delay_us(480); //480us以上SET_OP_1WIRE; //输出1CLR_DIR_1WIRE; //设置PA0 为输入 _delay_us(20); //15~60uswhile(CHECK_IP_1WIRE);SET_DIR_1WIRE;SET_OP_1WIRE;_delay_us(140); //60~240ussei();}void write_1820(unsigned char x){unsigned char m;for(m=0;m<8;m++){CLR_OP_1WIRE;if(x&(1<<m)) //写数据了,先写低位的! SET_OP_1WIRE;else{CLR_OP_1WIRE;}_delay_us(40); //15~60usSET_OP_1WIRE;}SET_OP_1WIRE;}unsigned char read_1820(void){unsigned char temp,k,n;temp=0;for(n=0;n<8;n++){CLR_OP_1WIRE;SET_OP_1WIRE;CLR_DIR_1WIRE;k=(CHECK_IP_1WIRE); //读数据,从低位开始 if(k)temp|=(1<<n);elsetemp&=~(1<<n);_delay_us(50); //60~120usSET_DIR_1WIRE;}return (temp);}void gettemp(void) //读取温度值{cli();init_1820(); //复位18b20write_1820(0xcc); // 发出转换命令write_1820(0x44);//_delay_ms(10); //不延时也好使,不知道怎么回事! init_1820();write_1820(0xcc); //发出读命令write_1820(0xbe);teml=read_1820(); //读数据temh=read_1820();sei();}#endif。
matlab环境下pc机与16位单片机串行通信的研究_图文(精)

入深的从概述USB和驱动程序的基本理论,继而根据DriverWorks的开发流程,重点介绍了其中的USB开发的设计,针对USB及驱动程序开发的初学者,使其能够便捷的了解USB和WDM模型驱动程序,并掌握开发工具中USB驱动开发的要点,快速的进入到驱动程序开发的工作中去。
参考文献[1]王志强.USB设备驱动程序开发技术研究.微计算机信息,2006[2]宁立革.基于嵌入式操作系统的USB驱动程序开发.微计算机信息,2005.[3]武安河.Windows2000/XP WDM设备驱动程序开发[….北京:电子工业出版社,2006.[4]薛园园.uSB应用开发技术大全[”]北京:人民邮电出版社,2007.作者简介田心~航天信息股份有限公司、数字技术研究院、芯片研发工程师,主要研究方向是信息安全领域的芯片研发与设计。
■MATLAB环境下PC机与16位单片机串行通信的研究1.汉泽西1.郭正虹2.彭宏文1.甘志强(1.西安石油大学电子工程学院2.中国石油测井有限公司长庆事业部摘要:文章提出一种PC机与16位单片机串行通信的设计方案。
利用控制工具箱serial类对象实现PC机与单片机SPCE061A间的异步串行通信,给出设计方案的硬件电路和部分软件程序,并通过对实验结果的分析说明串行通信的可靠性。
关键词:MATLAB,单片机,串行通信Research of SeriaI Com rnunication between PC and MCU In MATLAB Envi ronment1.Han Zexi1.6uo Zhenghong2.Peng Hongwen1.Gan Zhiqiang(1.Xi’an Shiyou University,Department of Electric Engineer(2.Chinese Petroleum Oil wel l logging Limited companyChangqing Services departmentAbstract:A method of serial communication between PC and16一bitS MCU in MATLAB Environment iS described.ThiS article employs serial Class object of the Instrument Toolbox provided by MATLAB to real ize the asynchronous serial communication between PC and16一bitS MCUw--SPCE061A.Concludes design method’S hardware Circuit and part of software programe.It alSO explain the reliabilitv of the communication result througth the analysiS of experiment result.Keywords:MATLAB,MCU,Serial Communlcation0.引言随着计算机系统的广泛应用和网络的飞速发展,各种控制设备间的通信功能显得越来越重要。
ATMEGA16的USART串口发送与接收数据示例程序

//ATMEGA16的USART串口发送与接收数据示例程序,采取中断的方式//发送200个FF,接收数据显示在数码管上,接收数据格式如09//编译环境 ICCAVR//系统时钟7.3728MHZ,设置熔丝位为外部高频石英晶体振荡,启动时间4.1ms//作者:David//日期:2013.10.20//*********************************************************************** // 包含文件//***********************************************************************#include <iom16v.h>#include <macros.h>#include <string.h>#include <stdio.h>#include <signal.h> //中断信号头文件//*********************************************************************** // 定义变量区//*********************************************************************** #define CH451_RESET 0x0201 //复位#define CH451_LEFTMOV 0x0300 //设置移动方式-左移#define CH451_LEFTCYC 0x0301 //设置移动方式-左循#define CH451_RIGHTMOV 0x0302 //设置移动方式-右移#define CH451_RIGHTCYC 0x0303 //设置移动方式-右循#define CH451_SYSOFF 0x0400 //关显示、键盘、看门狗#define CH451_SYSON1 0x0401 //开显示#define CH451_SYSON2 0x0403 //开显示、键盘#define CH451_SYSON3 0x0407 //开显示、键盘、看门狗功能#define CH451_DSP 0x0500 //设置默认显示方式#define CH451_BCD 0x058f //设置BCD译码方式#define CH451_TWINKLE 0x0600 //设置闪烁控制#define CH451_DIG0 0x0800 //数码管位0显示#define CH451_DIG1 0x0900 //数码管位1显示#define CH451_DIG2 0x0a00 //数码管位2显示#define CH451_DIG3 0x0b00 //数码管位3显示#define CH451_DIG4 0x0c00 //数码管位4显示#define CH451_DIG5 0x0d00 //数码管位5显示#define CH451_DIG6 0x0e00 //数码管位6显示#define CH451_DIG7 0x0f00 //数码管位7显示#define l ed0 0x0000 //数码管位0显示的数据0#define l ed1 0x0001 //数码管位0显示的数据1#define l ed2 0x0002 //数码管位0显示的数据2#define l ed3 0x0003 //数码管位0显示的数据3#define l ed4 0x0004 //数码管位0显示的数据4#define l ed5 0x0005 //数码管位0显示的数据5#define l ed6 0x0006 //数码管位0显示的数据6#define l ed7 0x0007 //数码管位0显示的数据7#define l edno 0x0010 //数码管灭#define dclk0 PORTD &= ~(1 << PD6) //串行数据时钟,上升延激活#define dclk1 PORTD |= (1 << PD6)#define din0 PORTD &= ~(1 << PD5) //串行数据输出,接CH451的数据输入#define din1 PORTD |= (1 << PD5)#define load0 PORTD &= ~(1 << PD4) //串行命令加载,上升延激活#define load1 PORTD |= (1 << PD4)#define uchar unsigned char#define uint unsigned int#define ulong unsigned long#define fosc 7372800 //晶振频率#define baud 9600 //设置波特率的大小uint tx_count=200,tx_flag=0xff;uchar A1,A2,A3;uchar usart_tx_data;uchar usart_rx_data;uchar table[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06, //显示用数据0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};//*************************************************************************// 初始化子程序//*************************************************************************void system_init(){PORTD=0x7F; //PD0设置为输入,PD1输出DDRD=0x72; //上拉电阻使能有效}void ch451_init() //先低后高,选择4线输入{din0;din1;}void usart_init(){UCSRB = 0x00;UCSRA=0x00; //单倍速模式UBRRL = (fosc/16/baud-1)%256; //写波特率的值UBRRH = (fosc/16/baud-1)/256;UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //UCSRC=086;写UCSRC寄存器 //异步通信无校验,8位数据1位停止位UCSRB=0xF8; //接收中断和发送中断允许}//***********************************************************************// 延时程序////***********************************************************************void delay_1ms(void){unsigned int i;for(i = 1; i < (unsigned int)(1144 - 2); i++);}void delay_ms(unsigned int n){unsigned int i = 0;while(i < n){delay_1ms();i++;}}//*************************************************************************// 数据处理函数//*************************************************************************void data_do(uchar temp_d){uchar A2t;A1=temp_d/100; //分出百,十,和个位A2t=temp_d%100;A2=A2t/10;A3=A2t%10;}//*************************************************************************// 串口相关中断服务子程序//************************************************************************* /* //数据发送结束中断向量#pragma interrupt_handler USART_TXC:14void USART_TXC() //中断服务程序{delay_ms(10); //相关操作}*///数据接收结束中断向量#pragma interrupt_handler USART_RXC:12void USART_RXC() //中断服务程序{CLI();//关中断usart_rx_data=UDR; //将接收到的数据取出data_do(usart_rx_data); //数据处理,得到个位十位百位SEI(); //开中断}/* //数据寄存器空中断向量#pragma interrupt_handler USART_UDRE:13void USART_UDRE() //中断服务程序{UDR=usart_tx_data; //发送数据到数据寄存器tx_count--;if(tx_count==0x00){tx_flag=0x01;}}*///************************************************************************* // 串口发送相关程序//************************************************************************* //发送单个字符void PutChar(char c){//PORTC |= (1 << PC3); //改变1487控制口为输出态,PC3=1 发送允许,接收禁止while(!(UCSRA & (1 << UDRE)));UDR = c;while(!(UCSRA&(1<<TXC)));UCSRA |= (1 <<TXC);//将发送结束标志位清零//PORTC &= ~(1 << PC3); //改变1487控制口为输出态,PC3=0 接收允许,发送禁止}//发送不带换行回车的字符串void PutNStr(unsigned char *Str){while (*Str != '\0'){PutChar(*Str);Str++;}}//发送带换行回车的字符串void PutStr(unsigned char *Str){while (*Str != '\0'){PutChar(*Str);Str++;}PutChar(0x0D);PutChar(0x0A);}//*************************************************************************// 输出命令子程序// 定义一无符号整型变量存储12字节的命令字//************************************************************************void ch451_write(unsigned int command){unsigned char i;load0; //命令开始for(i=0;i<12;i++){ //送入12位数据,低位在前if(command&1){din1;}elsedin0;dclk0;dclk1; //上升沿有效command>>=1;}load1; //加载数据}//*************************************************************************// 显示函数//*************************************************************************void display(uchar b_data,uchar s_data,uchar g_data){system_init();ch451_init();ch451_write(CH451_SYSOFF); //关显示、键盘、看门狗ch451_write(CH451_SYSON1); //开显示ch451_write(CH451_BCD); //设置BCD译码方式ch451_write(CH451_TWINKLE); //设置闪烁控制ch451_write(CH451_DIG0|table[b_data]); //显示接收到的值ch451_write(CH451_DIG1|table[s_data]);ch451_write(CH451_DIG2|table[g_data]);ch451_write(CH451_DIG3|ledno);ch451_write(CH451_DIG4|ledno);ch451_write(CH451_DIG5|ledno);ch451_write(CH451_DIG6|ledno);ch451_write(CH451_DIG7|ledno);}//*************************************************************************// 主程序//*************************************************************************void main(){system_init(); //系统初始化usart_init(); //usart串口初始化配置//usart_tx_data=0xff;SREG|=0x80; //开启全局中断while(1){/*while(tx_flag!=0x01) //数据发送是否完成,也可用发送完成中断 {//usart_tx_data=0xff;PutChar(0xFF);tx_count--;if(tx_count==0x00){tx_flag=0x01;}//delay_ms(10);}*///UCSRB=0xF0;display(A1,A2,A3); //显示接收到的数据 }}。
实现ATmega16单片机AD键盘与PC机的串口通信并用LCD1602显示程序

编程软件CodeVisionAV
实现功能:单片机与PC机(电脑)之间的串口通信。具体就是单片机最小系统上的AD键盘按键按下后发送键值到串口助手上显示,串口助手发送一串字符到最小系统上的lcd1602显示。
(程序或有冗余)
#include <mega16.h>
#include <delay.h>
data=rx_buffer[rx_rd_index]; //读取缓冲队列中的数据
if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#asm("cli") //关中断
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
delay_us(10);
ADCSRA|=0x40;
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
// USART Receiver buffer:接收器缓冲
#define RX_BUFFER_SIZE 8
char rx_buffer[RX_BUFFER_SIZE];
#if RX_BUFFER_SIZE<256
unsigned char rx_wr_index,rx_rd_index,rx_counter;
#else
unsigned int rx_wr_index,rx_rd_index,rx_counter;
#endif
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
本资料节选自手把手单片机系列教程,受版权保护,任何人不得肆意篡改发布,如需完整资料,请到周兴华培训中心官方网站查看,或者购买相关的手把手书籍ATMEGA16(L)的USART与PC机串行通信单片机与外界的信息交换可分为并行通信与串行通信两种。
并行通信是指一个数据的各位同时进行传送的通信方式。
优点是传送速度快,但传输线较多,并且只适合距离较短的通信。
串行通信是指一个数据是逐位顺序进行传送的通信方式。
其突出优点仅需单线就可进行通信,通信距离较远,缺点是传送的数据速率较低。
串行通信又有两种基本的通信方式:同步通信和异步通信。
10.1ATMEGA16(L)的异步串行收发器AVR单片机的异步串行收发器(USART)是一个高度灵活的串行通讯设备,图10-1为USAR图10-1USART的方框图USART主要分为三个部分:时钟发生器,发送器和接收器。
控制寄存器由三个单元共享。
时钟发生器包含同步逻辑,通过它将波特率发生器及为从机同步操作所使用的外部输入时钟同步起来。
XCK(发送器时钟)引脚只用于同步传输模式。
发送器包括一个写缓冲器,串行移位寄存器,奇偶发生器以及处理不同的帧格式所需的控制逻辑。
写缓冲器可以保持连续发送数据而不会在数据帧之间引入延迟。
由于接收器具有时钟和数据恢复单元,它是USART模块中最复杂的。
恢复单元用于异步数据的接收。
除了恢复单元,接收器还包括奇偶校验,控制逻辑,移位寄存器和一个两级接收缓冲器UDR。
接收器支持与发送器相同的帧格式,而且可以检测帧错误,数据过速和奇偶校验错误。
10.2U S ART的主要特点ATMEAG16(L)的USART特点如下:1.全双工操作(独立的串行接收和发送寄存器)2.异步或同步操作3.主机或从机提供时钟的同步操作4.高精度的波特率发生器5.支持5、6、7、8或9个数据位和1个或2个停止位6.硬件支持的奇偶校验操作7.数据过速检测8.帧错误检测9.噪声滤波,包括错误的起始位检测,以及数字低通滤波器10.三个独立的中断:发送结束中断,发送数据寄存器空中断,以及接收结束中断11.多处理器通讯模式12.倍速异步通讯模式10.3时钟产生10.3.1USART支持4种模式的时钟时钟产生逻辑为发送器和接收器产生基础时钟。
USART支持4种模式的时钟:正常的异步模式,倍速的异步模式,主机同步模式,以及从机同步模式。
USART控制位UMSEL和状态寄存器C(UCSRC)用于选择异步模式和同步模式。
倍速模式(只适用于异步模式)受控于UCSRA寄存器的U2X。
使用同步模式(UMSEL=1)时,XCK的数据方向寄存器(DDR_XCK)决定时钟源是由内部产生(主机模式)还是由外部生产(从机模式)。
仅在同步模式下XCK有效。
图10-2为时钟产生逻辑的框图。
图10-2时钟产生逻辑的框图10.3.2信号说明txclk-发送器时钟(内部信号)rxclk-接收器基础时钟(内部信号)xcki XCK-引脚输入(内部信号),用于同步从机操作xcko-输出到XCK引脚的时钟(内部信号),用于同步主机操作fosc-XTAL频率(系统时钟)10.3.3内部时钟用于异步模式与同步主机模式USART的波特率寄存器UBRR和降序计数器相连接,一起构成可编程的预分频器或波特率发生器。
降序计数器对系统时钟计数,当其计数到零或UBRRL寄存器被写时,会自动装入UBRR 寄存器的值。
当计数到零时产生一个时钟,该时钟作为波特率发生器的输出时钟,输出时钟的频率为fosc/(UBRR+1)。
发生器对波特率发生器的输出时钟进行2、8或16的分频,具体情况取决于工作模式。
波特率发生器的输出被直接用于接收器与数据恢复单元。
数据恢复单元使用了一个有2、8或16个状态的状态机,具体状态数由UMSEL、U2X与DDR_XCK位设定的工作模式决定。
表10-1给出了计算波特率(位/秒)以及计算每一种使用内部时钟源工作模式的UBRR值的公式。
使用模式波特率计算公式UBRR值的计算公式异步正常模式(U2X=0)foscBAUD=———————16(UBRR+1)foscUBRR=—————-116BAUD异步倍速模式foscBAUD=———————8(UBRR+1)foscUBRR=—————-18BAUD同步主机模式foscBAUD=———————2(UBRR+1)foscUBRR=—————-12BAUD表10-1计算波特率公式10.3.4倍速工作模式(U2X)通过设定UCSRA寄存器的U2X可以使传输速率加倍。
该位只对异步工作模式有效。
当工作在同步模式时,设置该位为“0”。
设置该位把波特率分频器的分频值从16降到8,使异步通信的传输速率加倍。
此时接收器只使用一半的采样数对数据进行采样及时钟恢复,因此在该模式下需要更精确的系统时钟与更精确的波特率设置。
发送器则没有这个要求。
10.3.5外部时钟同步从机操作模式由外部时钟驱动,如图10-2所示。
输入到XCK引脚的外部时钟由同步寄存器进行采样,用以提高稳定性。
同步寄存器的输出通过一个边沿检测器,然后应用于发送器与接收器。
这一过程引入了两个CPU时钟周期的延时,因此外部XCK的最大时钟频率由以下公式限制:f XCK <fOSC/410.3.6同步时钟操作使用同步模式时(UMSEL=1)XCK引脚被用于时钟输入(从机模式)或时钟输出(主机模式)。
时钟的边沿、数据的采样与数据的变化之间的关系的基本规律是:在改变数据输出端TxD的XCK时钟的相反边沿对数据输入端RxD进行采样。
UCRSC寄存器的UCPOL位确定使用XCK时钟的哪个边沿对数据进行采样和改变输出数据。
如图10-3所示,当UCPOL=0时,在XCK的上升沿改变输出数据,在XCK的下降沿进行数据采样;当UCPOL=1时,在XCK的下降沿改变输出数据,在XCK的上升沿进行数据采样。
10.4帧格式串行数据帧由数据字加上同步位(开始位与停止位)以及用于纠错的奇偶校验位构成。
10.4.1数据帧格式●1个起始位●5、6、7、8或9个数据位●无校验位、奇校验或偶校验位●1或2个停止位数据帧以起始位开始,紧接着是数据字的最低位,数据字最多可以有9个数据位,以数据的最高位结束。
如果使能了校验位,校验位将紧接着数据位,最后是结束位。
当一个完整的数据帧传输后,可以立即传输下一个新的数据帧,或使传输线处于空闲状态。
图10-3所示为数据帧结构组合。
括号中的位是可选的。
图10-3数据帧结构组合St-起始位,总是为低电平(n)-数据位(0~8)P-校验位,可以为奇校验或偶校验Sp-停止位,总是为高电平IDLE -通讯线上没有数据传输(RxD 或TxD ),线路空闲时必须为高电平数据帧的结构由UCSRB 和UCSRC 寄存器中的UCSZ2:0、UPM1:0、USBS 设定。
接收与发送使用相同的设置。
设置的任何改变都可能破坏正在进行的数据传送与接收。
USART的字长位UCSZ2:0确定了数据帧的数据位数;校验模式位UPM1:0用于使能与决定校验的类型;USBS位设置帧有一位或两位结束位。
接收器忽略第二个停止位,因此帧错误(FE)只在第一个结束位为“0”时被检测到。
10.4.2校验位的计算校验位的计算是对数据的各个位进行异或运算。
如果选择了奇校验,则异或结果还需要取反。
校验位与数据位的关系如下:P even =d n-1⊕…d 3⊕d 2⊕d 1⊕d 0+0P odd =d n-1⊕…d 3⊕d 2⊕d 1⊕d 0+1P even:偶校验结果P odd :奇校验位结果D n :第n个数据位校验位处于最后一个数据位与第一个停止位之间。
10.5U S ART 的寄存器及设置10.5.1USART I/O 数据寄存器(UDR)USART 发送数据缓冲寄存器和USART 接收数据缓冲寄存器共享相同的I/O 地址,称为USART 数据寄存器或UDR。
将数据写入UDR 时实际操作的是发送数据缓冲器存器(TXB),读UDR 时实际返回的是接收数据缓冲寄存器(RXB)的内容。
在5、6、7比特字长模式下,未使用的高位被发送器忽略,而接收器则将它们设置为0。
只有当UCSRA寄存器的UDRE标志置位后才可以对发送缓冲器进行写操作。
如果UDRE没有置位,那么写入UDR 的数据会被USART 发送器忽略。
当数据写入发送缓冲器后,若移位寄存器为空,发送器将把数据加载到发送移位寄存器。
然后数据串行地从TXD 引脚输出。
接收缓冲器包括一个两级FIFO,一旦接收缓冲器被寻址FIFO 就会改变它的状态。
因此不要对这一存储单元使用读-修改-写指令(SBI和CBI)。
使用位查询指令(SBIC和SBIS)时也要小心,因为这也有可能改变FIFO的状态。
10.5.2USART控制和状态寄存器A(UCSRA)●Bit7–RXC:USART接收结束。
接收缓冲器中有未读出的数据时RXC置位,否则清零。
接收器禁止时,接收缓冲器被刷新,导致RXC清零。
RXC标志可用来产生接收结束中断。
●Bit6–TXC:USART发送结束。
发送移位缓冲器中的数据被送出,且当发送缓冲器(UDR)为空时TXC置位。
执行发送结束中断时TXC标志自动清零,也可以通过写1进行清除操作。
TXC标志可用来产生发送结束中断。
●Bit5–UDRE:USART数据寄存器空。
UDRE标志指出发送缓冲器(UDR)是否准备好接收新数据。
UDRE为1说明缓冲器为空,已准备好进行数据接收。
UDRE标志可用来产生数据寄存器空中断。
复位后UDRE置位,表明发送器已经就绪。
●Bit4–FE:帧错误。
如果接收缓冲器接收到的下一个字符有帧错误,即接收缓冲器中的下一个字符的第一个停止位为0,那么FE置位。
这一位一直有效直到接收缓冲器(UDR)被读取。
当接收到的停止位为1时,FE 标志为0。
对UCSRA进行写入时,这一位要写0。
●Bit3–DOR:数据溢出。
数据溢出时DOR置位。
当接收缓冲器满(包含了两个数据),接收移位寄存器又有数据,若此时检测到一个新的起始位,数据溢出就产生了。
这一位一直有效直到接收缓冲器(UDR)被读取。
对UCSRA进行写入时,这一位要写0。
●Bit2–PE:奇偶校验错误。
当奇偶校验使能(UPM1=1),且接收缓冲器中所接收到的下一个字符有奇偶校验错误时UPE置位。
这一位一直有效直到接收缓冲器(UDR)被读取。
对UCSRA进行写入时,这一位要写0。
●Bit1–U2X:倍速发送。
这一位仅对异步操作有影响。
使用同步操作时将此位清零。
此位置1可将波特率分频因子从16降到8,从而有效的将异步通信模式的传输速率加倍。
●Bit0–MPCM:多处理器通信模式。
设置此位将启动多处理器通信模式。
MPCM置位后,USART接收器接收到的那些不包含地址信息的输入帧都将被忽略。