avr单片机的缓冲区串口收发,别的单片机 你改一下寄存器就行
//芯片:mega16
#include
#define F 8000000
#define BAUD 9600
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
void usart_init(void);
char get_char(void);
void put_char(char c);
#define RX_SIZE 20
#define TX_SIZE 20
char rx[RX_SIZE];
u8 rx_head,rx_rear,rx_overflow;
char tx[TX_SIZE];
u8 tx_head,tx_rear,tx_overflow;
int main(void)
{
usart_init();
put_char( 'a' );
put_char( 'b' );
put_char( 'c' );
put_char( 'd' );
put_char( 'e' );
while(1)
put_char(get_char());
}
void usart_init(void)
{
UCSRB = (1<<RXCIE)|(1<<TXCIE)|(1<<RXEN)|(1<<TXEN);//接收结束中断使能,发送结束中断使能,接收允许,发送允许
UCSRC = 0X86; //选择UCSRC,异步模式,无校验,1位停止位,8位数据位
UBRRH = (F/16/BAUD - 1)>>8; //选择UBRRH,设置波特率
UBRRL = (unsigned char)(F/16/BAUD - 1);
rx_head = 0;
rx_rear = 0;
rx_overflow = 0;
tx_head = 0;
tx_rear = 0;
tx_overflow = 0;
asm("sei");
}
char get_char(void)
{
char c;
while(rx_head == rx_rear);//如果接收缓冲区空,则一直等待
c = rx[rx_head++]; //从头取数据,头+1
if(rx_head >= RX_SIZE ) rx_head = 0;//若头超出缓冲区末端,移至缓冲区开端
return c;
}
void put_char(char c)
{
if(tx_head != tx_rear || !( UCSRA&(1<<UDRE) ) )//若 发送缓冲区非空 或 发送寄存器非空
{
tx[tx_rear++] = c;//将c移至缓冲区尾,尾+1
if(tx_rear >= TX_SIZE ) tx_rear = 0;//若尾超出缓冲区末端,移至缓冲区开端
if(tx_rear == tx_head)//若尾前进到头,说明缓冲区满
{
tx_overflow = 1;//缓冲区溢出 (事实上刚好不溢出,这里为了编程方便,牺牲一个字节并记为溢出)
tx_head++;//牺牲最早接收的那个字节
}
}
else
UDR = c;//直接发送
}
#pragma vector = USART_RXC_vect
__interrupt void receive(void)
{
rx[rx_rear++] = UDR;
if(rx_rear >= RX_SIZE ) rx_rear = 0;//若尾超出缓冲区末端,移至缓冲区开端
if(rx_rear == rx_head)//若尾前进到头,说明缓冲区满
{
rx_overflow = 1;//缓冲区溢出 (事实上刚好不溢出,这里为了编程方便,牺牲一个字节并记为溢出)
rx_head++;//牺牲最早接收的那个字节
}
}
#pragma vector = USART_TXC_vect
__interrupt void transmit(void)
{
if(tx_head != tx_rear)//如果发送缓冲区非空
{
UDR = tx[tx_head++];//发送头数据,头+1
if(tx_head >= TX_SIZE) tx_head = 0;//若头超出缓冲区末端,移至缓冲区开端
}
}
做一个整形到ASCII的转换函数。如果你要发送的数据最大值可以确定,可以根据最大值定义一个ASCII数组,数组的每一个单元存放整形数据的一位。
发送前先对发送整形数组里的单元转换成ASCII数组,然后再按照通用的发送函数进行发送。
void InttoChar (uint IntNumber)
//---------------------------------------------------------
// Name: void InttoChar (int IntNumber)
// Func: Translate integer to ASCII charactor array
// Char: IntNumber number to be translated to ASCII charactor
//---------------------------------------------------------
{
if (IntNumber < 10)
{
AsciiArray[0] = IntNumber + 0x30;
AsciiArray[1] = 0x20;
AsciiArray[2] = 0x20;
AsciiArray[3] = 0x20;
AsciiArray[4] = 0x20;
return;
}
if (IntNumber < 100)
{
AsciiArray[0] = IntNumber / 10 + 0x30;
AsciiArray[1] = IntNumber % 10 + 0x30;
AsciiArray[2] = 0x20;
AsciiArray[3] = 0x20;
AsciiArray[4] = 0x20;
return;
}
if (IntNumber < 1000)
{
AsciiArray[0] = IntNumber / 100 + 0x30;
AsciiArray[1] = IntNumber % 100 / 10 + 0x30;
AsciiArray[2] = IntNumber % 10 + 0x30;
AsciiArray[3] = 0x20;
AsciiArray[4] = 0x20;
return;
}
if (IntNumber < 10000)
{
AsciiArray[0] = IntNumber / 1000 + 0x30;
AsciiArray[1] = IntNumber % 1000 / 100 + 0x30;
AsciiArray[2] = IntNumber % 100 / 10 + 0x30;
AsciiArray[3] = IntNumber % 10 + 0x30;
AsciiArray[4] = 0x20;
return;
}
else
{
AsciiArray[0] = IntNumber / 10000 + 0x30;
AsciiArray[1] = IntNumber % 10000 / 1000 + 0x30;
AsciiArray[2] = IntNumber % 1000 / 100 + 0x30;
AsciiArray[3] = IntNumber % 100 / 10 + 0x30;
AsciiArray[4] = IntNumber % 10 + 0x30;
return;
}
}
呵呵,楼主没搞清楚ASCII码的概念。
把数组定义成:unsigned
char
b[8]={'1','2','3','4','5','6','7','8'};
或者
unsigned
char
b[8]={0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38};
就可以了。
在计算机上能显示的是ASCII码,比如1的ASCII码数值是0x31。
而ASCII值
1
是一个不可见字符,也就是你所见的乱码。
另一种解决方法,设置你的串口助手按16进制显示,乱码就能看到了。
第一,你要解决数据是否同步的问题。电脑的频率比单片机的时钟频率快很多,所以串行通信选择同步传输。当单片机发送完数组的第一个数据,上位机接收到这个数据后发送一个应答信号给单片机,然后单片机收到应答信号接着发送第二个数据给上位机,以此类推(应答信号的具体数值是你的通讯协议定义的)
第二,你的vb要添加MSComm控件,参考文章
>
接收的数串口,接收后可以存储到数组里面。比如:
void uart() interrupt 4
{
static i;
if(RI)
{
RI=0;
buf[i]=SBUF;
}
}
以上就是关于c51,单片机从串口接收字符串,放到一个数组里面,然后在通过串口发出去。急!谢谢全部的内容,包括:c51,单片机从串口接收字符串,放到一个数组里面,然后在通过串口发出去。急!谢谢、c51语言编写,串口通讯程序,实现AT89S52单片机把一个整型数组数据,发送给VB、求指点一个关于 串口传递数组的程序 错误等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)