单片机教程网

电脑版
提示:原网页已由神马搜索转码, 内容由www.51hei.com提供.
查看:973|回复:3
打印上一主题下一主题

m8单片机串口通讯程序

[复制链接]
跳转到指定楼层
楼主
ID:1104531发表于 2024-1-11 21:08|只看该作者回帖奖励
个人认为,AVR系列的串口使用还是比较容易出错,如果采用传统的查询方式太耗系统时间,而且现在关于AVR的教材大多给你的是查询发送方式,中断接收方式。
本例子是采用中断接收,中断发送方式。希望对大家有所帮助。

//ICC-AVR
// Target : M8
// Crystal: 4.0000Mhz

#include< iom8v.h>
#include< macros.h>

#define DISABLE_UARTTX()       UCSRB&=~BIT(TXCIE)
#define ABLE_UARTTX()           UCSRA|=BIT(TXC);UCSRB|=BIT(TXCIE)

unsigned char ucRecv;
unsigned char ucRecvOk;

unsigned char ucSendData[8]="Recv OK!";
unsigned char ucComSendCnt,ucComSendPtr;


void InitPort(void)
{
       PORTB = 0xFF;
       DDRB  = 0x00;
       PORTC = 0x7F; //m103 output only
       DDRC  = 0x00;
       PORTD = 0xFE;
       DDRD  = 0x02;
}

//UART0 initialize
// desired baud rate: 2400
// actual: baud rate:2404 (0.2%)
void InitUart0(void)
{
       UCSRB = 0x00; //disable while setting baud rate
       UCSRA = 0x00;
       UCSRC = BIT(URSEL) | 0x06;
       UBRRL = 0x67; //set baud rate lo
       UBRRH = 0x00; //set baud rate hi
       UCSRB = 0x98;
}

#pragma interrupt_handler uart0_rx_isr:iv_USART0_RXC
void uart0_rx_isr(void)
{
       unsigned char ucTmp;
//uart has received a character in UDR
       ucTmp=UDR;
       if (ucTmp=='A')
       {
           ucRecv=ucTmp;
           ucRecvOk=0x01;      
       }
}


#pragma interrupt_handler uart0_tx_isr:iv_USART0_TXC
void uart0_tx_isr(void)
{
//character has been transmitted
       if (ucComSendCnt!=0)
       {
             ucComSendPtr+=1;
             UDR=ucSendData[ucComSendPtr];
           ucComSendCnt-=1;
       }else
       {      
           //PORTB&=~BIT(PB_COM_LED);                           //串口指示灯灭
           DISABLE_UARTTX();
           //PORTB^=BIT(PB_COM_LED);                           //串口指示灯灭
       }
}



//call this routine to initialize all peripherals
void InitMcu(void)
{
//stop errant interrupts until set up
       CLI();                 //disable all interrupts
       InitPort();
       InitUart0();

       MCUCR = 0x00;
       GICR  = 0x00;
       TIMSK = 0x00;       //timer interrupt sources
       SEI();                 //re-enable interrupts
                             //all peripherals are now initialized
}



void main(void)
{
       unsigned char i;
       InitMcu();
       while(1)
       {
           if (ucRecvOk==0x01)
           {
                 CLI();
                 ucRecvOk=0;
                 SEI();
                
                 ucComSendCnt=7;
                 ucComSendPtr=0;
                 ABLE_UARTTX();
                 UDR=ucSendData[0];
           }      
       }
}

m8 串口通讯.zip

44.24 KB, 下载次数: 4, 下载积分: 黑币 -5

评分

黑币 +50
收起理由
+ 50
共享资料的黑币奖励!

查看全部评分

沙发
ID:229502发表于 2024-2-11 21:18|只看该作者
楼主能否有个注解,对初学者更友好
板凳
ID:1126818发表于 2024-8-30 21:59来自手机|只看该作者
新手上路,多多指教。有没有发送十六进的程序?
地板
ID:342822发表于 2024-9-1 19:17|只看该作者
用文心一言给他来个中文注释:
#include< iom8v.h> // 包含特定于ATmega8V或其他兼容AVR型号的头文件,提供寄存器定义等  
#include< macros.h> // 包含宏定义,可能用于简化位操作或寄存器访问  
  
// 定义宏来启用和禁用UART发送完成中断  
#define DISABLE_UARTTX()       UCSRB& = ~BIT(TXCIE) // 清除UCSRB寄存器中的TXCIE位,禁用UART发送完成中断  
#define ABLE_UARTTX()         UCSRA |= BIT(TXC); UCSRB |= BIT(TXCIE) // 设置UCSRA的TXC位和UCSRB的TXCIE位,准备发送并启用中断  
  
// 全局变量,用于接收和发送数据  
unsigned char ucRecv; // 接收到的字符  
unsigned char ucRecvOk; // 接收标志,接收到特定字符时置位  
  
unsigned char ucSendData[8]="Recv OK!"; // 要发送的数据  
unsigned char ucComSendCnt, ucComSendPtr; // 发送计数器和指针  
  
// 初始化GPIO端口  
void InitPort(void)  
{  
   PORTB = 0xFF; // 设置PORTB的所有位为高电平(具体功能取决于硬件连接)  
   DDRB  = 0x00; // 设置PORTB为输入模式  
   PORTC = 0x7F; // 设置PORTC的部分位为高电平(假设m103为输出)  
   DDRC  = 0x00; // 设置PORTC为输入模式  
   PORTD = 0xFE; // 设置PORTD的特定位为高电平  
   DDRD  = 0x02; // 设置PORTD的特定位为输出模式  
}  
  
// 初始化UART0  
// 设定波特率为2400,但实际可能略有偏差(如2404)  
void InitUart0(void)  
{  
   UCSRB = 0x00; // 在设置波特率时禁用UART  
   UCSRA = 0x00; // 清除UCSRA寄存器  
   UCSRC = BIT(URSEL) | 0x06; // 设置UCSRC寄存器以启用异步USART模式,并设置字符大小为8位  
   UBRRL = 0x67; // 设置波特率低位  
   UBRRH = 0x00; // 设置波特率高位  
   UCSRB = 0x98; // 启用接收器和发送器,设置接收中断使能  
}  
  
// UART接收中断服务例程  
#pragma interrupt_handler uart0_rx_isr:iv_USART0_RXC  
void uart0_rx_isr(void)  
{  
   unsigned char ucTmp;  
   // UART已接收到一个字符  
   ucTmp = UDR; // 从UDR寄存器读取接收到的字符  
   if (ucTmp == 'A') // 如果接收到的字符是'A'  
   {  
       ucRecv = ucTmp; // 保存接收到的字符  
       ucRecvOk = 0x01; // 设置接收标志  
   }  
}  
  
// UART发送中断服务例程  
#pragma interrupt_handler uart0_tx_isr:iv_USART0_TXC  
void uart0_tx_isr(void)  
{  
   // 字符已发送  
   if (ucComSendCnt != 0) // 如果还有字符需要发送  
   {  
       ucComSendPtr += 1; // 发送指针递增  
       UDR = ucSendData[ucComSendPtr]; // 发送下一个字符  
       ucComSendCnt -= 1; // 发送计数器递减  
   }  
   else  
   {  
       // 发送完成,禁用UART发送中断  
       DISABLE_UARTTX();  
       // 注释掉的代码可能用于控制串口指示灯  
   }  
}  
  
// 初始化微控制器所有外设  
void InitMcu(void)  
{  
   // 在设置完成前停止错误中断  
   CLI(); // 禁用所有中断  
   InitPort(); // 初始化GPIO端口  
   InitUart0(); // 初始化UART0  
  
   MCUCR = 0x00; // 清除MCU控制寄存器  
   GICR  = 0x00; // 清除全局中断控制寄存器(注意:某些AVR型号可能没有GICR)  
   TIMSK = 0x00; // 清除定时器中断源掩码寄存器(此处用于确保没有定时器中断)  
   SEI(); // 重新启用中断  
   // 所有外设现已初始化完成  
}  
  
// 主函数  
void main(void)  
{  
   unsigned char i; // 未使用的变量,可能用于调试或保留  
   InitMcu(); // 初始化微控制器  
   while(1) // 无限循环  
   {  
       if (ucRecvOk == 0x01) // 如果接收到特定字符  
       {  
         CLI(); // 禁用中断  
         ucRecvOk = 0; // 清除接收标志  
         SEI(); // 重新启用中断  
  
         ucComSendCnt = 7; // 设置发送计数器  
         ucComSendPtr = 0; // 重置发送指针  
         ABLE_UARTTX(); // 准备发送并启用发送中断  
         UDR = ucSendData[0]; // 发送第一个字符以启动发送过程  
       }  
   }  
}

手机版|小黑屋|51黑电子论坛|51黑电子论坛6群QQ管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网