atmega16串口通信
基于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);}}}。
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。
Atmega16串行口

⑹采用3线串行接口传送数据。(仅使用单片机3个I/O口)
8.2 MAX7219 显示控制芯片
8.2.3 MAX7219的工作原理
⑴数据通信:采用串行通信接收数据。 内部为16位移位寄存器。数据分两次移入。最先移入的数据 是D15,最后移入的数据是D0。 ⑵数据格式:
RAM或SFR地址 D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D 4 D3 D 2 D1 D0 显示数据或控制字
… … …
MAX7219
…
…
…
SEGG
Atmega16
DIG7 … DIG2 DIG1 DIG0
内部RAM 5 7 3 9 6 2 6 9
…
寄存器SFR
8.2 MAX7219 显示控制芯片
主单片机源程序:
#include <mega16.h> #include <delay.h> unsigned char a[100]; unsigned char b[100]; unsigned char i=0; // SPI interrupt service routine interrupt [SPI_STC] void spi_isr(void) { b[i]=SPDR; if (i=100) SPCR=0X00; else { delay_us(3); SPDR=a[i+1]; i++; }
SPI状态寄存器——SPSR
SPIF:SPI中断标志。当串行传送完成时,SPIF置1。若此 时寄存器SPCR的SPIE和全局中断使能位置位,SPI中断 即产生。如果SPI为主机,SS配置为输入,且被拉低, SPIF也将置位。清零SPIF的两种方式: 硬件方式。进入中断服务程序时,SPIF由硬件自动清零。 先读SPSR,紧接着访问SPDR来对SPIF清零。 WCOL:写冲突标志。在发送当中对SPI数据寄存器SPDR 写数据将置位WCOL。WCOL清零:可以通过先读SPSR, 紧接着访问SPDR来清零。 SPI2X: 倍速SPI。置位后SPI的速度加倍。若为主机则 SCK 频率可达CPU频率的一半。若为从机,SCK必须低 于fosc /4
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
ATMEGA16_串口接收程序

SREG=0X80;//打开全局中断
}
/****************************************************
发送数据函数
****************************************************/
写数据函数规定写数据的流程
*******************************************/
void write_data(uchar data) //data
{
uchar start_data,Hdata,Ldata;
start_data=0xfa; //写数据
Hdata=data&0xf0; //取高四位
Ldata=(data<<4)&0xf0; //取低四位
sendbyte(start_data);//发送起始信号
delay_us(1);
sendbyte(Hdata);//发送高四位
delay_us(1);
sendbyte(Ldata);//发送低四位
delay_us(1);
}
/**********************************************
LCD初始化函数
************************************************/
void LCD_init()
{
write_com(0x01);
delay(5) ; //清屏指令
ATMEGE16_SPI通讯 _Master

2012/8/8/**************************************2012.7.19功能:实现atmega16单片机SPI通讯_主机模式接线: PB4=SS, PB5=MOSI , PB6=MISO ,PB7=SCK开发环境:ICCAVR****************************************/#include <iom16v.h>#include <macros.h>#define uint unsigned int#define uchar unsigned char/***********************系统函数**********************/void delay(uint ms){uint i,j;for(i=0;i<ms;i++){for(j=0;j<1140;j++);}}/**************************************端口初始化***************************************/void port_init(void){PORTB = 0x00;DDRB = 0x00;}/***************************************SPI 初始化***********************************///SPI initialize// clock rate: 57599hz//PB4=SS, PB5=MOSI PB6=MISO PB7=SCKvoid spi_init(void){PORTB |= (1<<PB4) | (1<<PB5) | (1<<PB6) | (1<<PB7);DDRB |= (1<<DDB5) | (1<<DDB7) | (1<<DDB4); //Set MOSI, SCK AND SS as outputs SPCR = 0x73; //setup SPI //SPCR=(1<<SPI)|(1<<DORD)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0)// 使能SPI 数据次序主从选择频率分频64 分频SPSR = 0x00; //setup SPI}/******中断服务函数***************/ //call this routine to initialize all peripherals void init_devices(void){ //stop errant interrupts until set upCLI(); //disable all interrupts 关闭全局中断//port_init();spi_init();SEI(); //re-enable interrupts打开全局中断//all peripherals are now initialized}void SPI_MasterTransmit(char cData){PORTB &=~ (1<<PB4); //强制接收方进入从模式使能SPISPCR |= (1<<MSTR); // MSTR有时会被清零,这里强制进入主机模式/* 启动数据传输*/SPDR = cData; //SPCR SPI控制寄存器/* 等待传输结束*/ //SPDR SPI数据寄存器while(!(SPSR & (1<<SPIF))) //SPSR SPI状态寄存器; //SPIF 中断标志位PORTB |= (1<<PB4); //关闭SPI}//主函数void main(void){unsigned char i=0;init_devices();while(1){SPI_MasterTransmit(0xAA);delay(500);SPI_MasterTransmit(0X55);delay(500);SPI_MasterTransmit(0XFF);delay(500);SPI_MasterTransmit(0X00);delay(500);/********************for(i=255;i>0;i--){SPI_MasterTransmit(i); delay(100);}***********************/ }}。
AVR单片机项目十二 ATmega16单片机I2C通信接口应用

【任务1】 项目知识点学习 二、I2C总线的协议
3、I2C总线的仲裁
图12-3 I2C总线的仲裁过程
【任务1】 项目知识点学习 二、I2C总线的协议
4、I2C总线的数据传输
图12-4 I2C总线的数据传输过程
【任务1】 项目知识点学习 二、I2C总线的协议
4、I2C总线的数据传输
图12-5 I2C总线的数据传输格式图
【任务1】 项目知识点学习 三、时钟芯片PCF8563的相关知识
3、时钟芯片PCF8563的基本原理及内部寄存器概述
所有16个寄存器设计成可寻址的8位并行寄存器,但不 是所有位都有用。前两个寄存器(内存地址00H,01H ) 用于控制寄存器和状态寄存器,内存地址02H~08H用于 时钟计数器(秒~年计数器),地址09H~0CH用于报警 寄存器(定义报警条件),地址0DH控制CLKOUT管脚的 输出频率,地址0EH 和0FH分别用于定时器控制寄存器和 定时器寄存器。秒、分钟、小时、日、月、年、分钟报警 、小时报警、日报警寄存器,编码格式为BCD,星期和星 期报警寄存器不以BCD格式编码。
单片机应用技术
项目十二
ATmega16单片机I2C通信接口应用
【知识目标】
掌握SPI串行通信协议 了解ATmega16单片机SPI串行通信接口结构 了解与SPI串行通信有关的寄存器的功能 了解TLC5615D/A芯片
【能力目标】 掌握ATmega16单片机的I2C串行通信接口相关寄 存器的配置方法 掌握PCF8563无线通信模块方法 掌握简单的单片机I2C串行通信总线系统程序的编 写、调试方法
【任务1】 项目知识点学习 三、时钟芯片PCF8563的相关知识
1、时钟芯片PCF8563概述 PCF8563 是PHILIPS 公司推出的一款工业级内含I2C 总线接口功能的具有极低功耗的多功能时钟/日历芯片。具 有多种报警功能、定时器功能、时钟输出功能以及中断输 出功能能完成各种复杂的定时服务,甚至可为单片机提供 看门狗功能。内部时钟电路内部振荡电路、内部低电压检 测电路1.0V 以及两线制I2C 总线通讯方式,不但使外围电 路及其简洁,而且也增加了芯片的可靠性。同时每次读写 数据后,内嵌的字地址寄存器会自动产生增量。当然作为 时钟芯片,亦解决了2000 年问题。已被广泛用于电表、水 表、电话、便携式仪器及电池供电的仪器仪表等产品领域。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
atmega16串口通信ATmega16 单片机带有一个全双工的通用同步/异步串行收发模块USART,该接口是一个高度灵活的串行通讯设备。
其主要特点如下:全双工操作,可同时进行收发操作;支持同步或异步操作;支持5、6、7、8 和9 位数据位,1 位或者2 位停止位的串行数据帧结构;三个完全独立的中断,TX 发送完成,TX 发送数据寄存器空,RX 接收完成;支持多机通讯模式;相关寄存器:USART 数据寄存器—UDR;USART 控制和状态寄存器—UCSRA,UCSRB,UCSRC;波特率寄存器—UBRRL 和UBRRH;串口背景知识(1)串行通讯简介串行同步通讯容易理解,约定一个同步时钟,每一时刻传输线上的信息就是要传送的信息单元。
串行异步通讯是把一个字符看作一个独立的信息单元,每一个字符中的各位是以固定的时间传送。
因此,这种传送方式在同一字节内部是同步的,而字符间是异步的。
在异步通信中收发双方取得同步的方法是采用在字符格式中设置起始位,而在字符结束时发送1~2 个停止位。
当接收器检测到起始位时,便能知道经接着的是有效的字符位,于是开始接收字符,检测到停止位时,就将接收到的有效字符装载到接收缓冲器中。
最简单的串口通信使用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,奇偶校验位:在串口通信中一种简单的检错方式。
有四种检错方式:偶、奇、高和低。
当然没有校验位也是可以的。
对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。
例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。
如果是奇校验,校验位位1,这样就有3个逻辑高位。
高位和低位不真正的检查数据,简单置位逻辑高或者逻辑低校验。
这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步通常异步通信的格式如图:USART 接受以下30 种组合的数据帧格式:• 1 个起始位• 5、 6、 7、 8 或9 个数据位• 无校验位、奇校验或偶校验位• 1或2 个停止位数据帧以起始位开始;紧接着是数据字的最低位,数据字最多可以有9 个数据位,以数据的最高位结束。
如果使能了校验位,校验位将紧接着数据位,最后是结束位。
当一个完整的数据帧传输后,可以立即传输下一个新的数据帧,或使传输线处于空闲状态。
数据帧的结构由UCSRB 和 UCSRC 寄存器中的UCSZ2:0、 UPM1:0、USBS 设定。
接收与发送使用相同的设置。
设置的任何改变都可能破坏正在进行的数据传送与接收。
(2)串口的组成串口由阴阳两种接口组成。
最常使用的信号引脚是TD、RD 和SG,因此最简单的串口调试只需要包含3 条引线就可以了。
在RS232(一种串行工业总线标准)标准中,利用RD、TD 作为接收、发送信号线,加入地线,约定好通讯的波特率,实现串行信号传输。
(3)串口电平转换电路PC 的串口工作TTL 信号是12V 的,而在我们一般使用的电路板上,电源信号和TTL 电平是5V 的(在低功耗电路中是3.3V 的),为了将信号转化为可用,需要做串口的电平转换。
这一部分电路已经有相应的生产厂商做出了各种集成芯片,例如MAXIM 公司的MAX232/MAX233 芯片,就是实现5V 电路中和PC 实现串口通信的电平转换芯片,而MAX3232/MAX3233 可以实现3.3V 的电平转换。
串口寄存器介绍USART I/O 数据寄存器- UDRUSART 发送数据缓冲寄存器和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 的状态。
USART 控制和状态寄存器A -UCSRA• Bit 7 – RXC: USART 接收结束接收缓冲器中有未读出的数据时RXC 置位,否则清零。
接收器禁止时,接收缓冲器被刷新,导致RXC 清零。
RXC 标志可用来产生接收结束中断( 见对RXCIE 位的描述)。
• Bit 6 – TXC: USART 发送结束发送移位缓冲器中的数据被送出,且当发送缓冲器(UDR) 为空时TXC 置位。
执行发送结束中断时TXC 标志自动清零,也可以通过写1 进行清除操作。
TXC 标志可用来产生发送结束中断( 见对TXCIE 位的描述)。
• Bit 5 – UDRE: USART 数据寄存器空UDRE标志指出发送缓冲器(UDR)是否准备好接收新数据。
UDRE为1说明缓冲器为空,已准备好进行数据接收。
UDRE标志可用来产生数据寄存器空中断(见对UDRIE位的描述)。
复位后UDRE 置位,表明发送器已经就绪。
• Bit 4 – FE: 帧错误如果接收缓冲器接收到的下一个字符有帧错误,即接收缓冲器中的下一个字符的第一个停止位为0,那么FE 置位。
这一位一直有效直到接收缓冲器(UDR) 被读取。
当接收到的停止位为1 时, FE 标志为0。
对UCSRA 进行写入时,这一位要写0。
• Bit 3 – DOR: 数据溢出数据溢出时DOR 置位。
当接收缓冲器满( 包含了两个数据),接收移位寄存器又有数据,若此时检测到一个新的起始位,数据溢出就产生了。
这一位一直有效直到接收缓冲器(UDR) 被读取。
对UCSRA 进行写入时,这一位要写0。
• Bit 2 – PE: 奇偶校验错误当奇偶校验使能(UPM1 = 1),且接收缓冲器中所接收到的下一个字符有奇偶校验错误时UPE 置位。
这一位一直有效直到接收缓冲器 (UDR) 被读取。
对UCSRA 进行写入时,这一位要写0。
• Bit 1 – U2X: 倍速发送这一位仅对异步操作有影响。
使用同步操作时将此位清零。
此位置1 可将波特率分频因子从16 降到8,从而有效的将异步通信模式的传输速率加倍。
• Bit 0 – MPCM: 多处理器通信模式设置此位将启动多处理器通信模式。
MPCM 置位后,USART 接收器接收到的那些不包含地址信息的输入帧都将被忽略。
发送器不受MPCM设置的影响。
详细信息请参考 P150“多处理器通讯模式” 。
USART 控制和状态寄存器B -UCSRB• Bit 7 – RXCIE: 接收结束中断使能置位后使能RXC 中断。
当RXCIE 为1,全局中断标志位SREG 置位, UCSRA 寄存器的RXC 亦为1 时可以产生USART 接收结束中断。
• Bit 6 – TXCIE: 发送结束中断使能置位后使能TXC 中断。
当TXCIE 为1,全局中断标志位SREG 置位,UCSRA 寄存器的TXC 亦为1 时可以产生USART 发送结束中断。
• Bit 5 – UDRIE: USART 数据寄存器空中断使能置位后使能UDRE 中断。
当UDRIE 为1,全局中断标志位SREG 置位,UCSRA 寄存器的UDRE 亦为1 时可以产生USART 数据寄存器空中断。
• Bit 4 – RXEN: 接收使能置位后将启动USART 接收器。
RxD 引脚的通用端口功能被USART 功能所取代。
禁止接收器将刷新接收缓冲器,并使 FE、DOR 及PE 标志无效。
• Bit 3 – TXEN: 发送使能置位后将启动将启动USART 发送器。
TxD 引脚的通用端口功能被USART 功能所取代。
TXEN 清零后,只有等到所有的数据发送完成后发送器才能够真正禁止,即发送移位寄存器与发送缓冲寄存器中没有要传送的数据。