1. 相关寄存器:
1. SCIBDH,SCIBDL:波特率寄存器(SCIBDH只有低5位有效)
波特率 = 总线频率 / (16 * SBR[12:0])
2. SCICR2: SCI控制寄存器2
位数 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
含义 | TIE | TCIE | RIE | ILIE | TE | RE | RWU | SBK |
复位值 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
TIE: 发送中断使能位。使能发送数据寄存器空标志(TDRE)来产生中断申请
TCIE: 发送完成中断使能位。使能发送完成标志(TC)来产生中断申请
RIE: 接收器满中断使能位
TE: 发送器使能位
RE: 接收器使能位
3. SCISR1: SCI状态寄存器1
位数 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
含义 | TDRE | TC | RDRF | IDLE | OR | NF | FE | PF |
复位值 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
TDRE: 发送数据寄存器空标志
TC: 发送完成标志
RDRF: 接收数据寄存器满标志
4. SCIDRL,(SCIDRH): SCI数据寄存器
2.寄存器使用注意事项:
1. TDRE(TC)复位值为1,因此将SCICR2的TIE(TCIE)置为1即可产生中断
2. TDRE,TC的清除方法:读SCISR1,然后写SCIDRL,注意,发送完最后一个字节之后,会产生中断,但因为这是最后一个字节,故不会写SCIDRL,中断标志仍然存在
3. RDRF的清除方法:读SCISR1,然后读SCIDRL。
3.示例函数;
说明:
1. 发送和接收都采用中断方式,以帧为基本处理单元,当接收到一帧完整数据时,置位接收标志,主程序不断查询接收标志,若接收标志置位,则调用接收处理函数解析接收到的帧。
2. 通信协议基本形式:帧头(1字节) +通信头(1字节) +通信数据长度(1字节) +通信数据+校验字(1字节)
通信头: 表示通信的内容
通信数据长度 = 通信数据长度 + 校验字长度
- // ============================================================================
- // SCI初始化程序
- // 注:总线时钟为40MHZ
- // baudrate = 153600,即9600bytes/s 使能接收中断(实际:156250bps)
- // ============================================================================
- void SCI_Init(void)
- {
- // SCI1
- SCI1BDH = 0X00; // baud rate = bus clock / (16*SBR[12:0]) 波特率153600,SBR[12:0]= 16 = 0X0F;
- SCI1BDL = 0X0F;
- SCI1CR2 = 0x2C; // 接收使能,接收器满中断使能,发送使能
- }
- // ============================================================================
- // 发送数据请求函数
- // 如果没有数据正在发送,则立即发送,如果有数据正在发送,则置位发送请求标志位
- // 主流程不断查询发送请求标志位,若有该标志位,且没有数据正在发送则发送
- // ============================================================================
- void Send(byte commd)
- {
- SCI_Commd=commd;
- if(Status.Bits.Uart_R_Over==0) // 发送完成
- {
- Send_1();
- }
- else
- {
- Status.Bits.Uart_T_Commd=1; // 置位发送请求标志
- }
- }
- // ============================================================================
- // 发送函数
- // Pre_Send():发送预处理函数,根据通信头(commd)内容处理发送缓冲区
- // ============================================================================void Send_1(void)
- {
- Pre_Send();
- Status.Bits.Uart_R_Over = 1; // 置位正在发送标志
- SCI1CR2 |= 0x40; // 使能中断
- }// ============================================================================
- // 串口中断程序
- // 中断接收和中断发送
- // ============================================================================
- interrupt void SCI1_INT(void)
- {
- static byte R_num = 0, R_curr = 0; // 接收数据总数和当前指针
- static byte T_num = 0, T_curr = 0; // 发送数据总数和当前指针
- if(SCI1SR1_RDRF == 1) // 接收中断
- {
- Uart_R_Str[R_curr] = SCI1DRL;
- R_curr++;
- // 判断是否为帧头
- if(R_curr == 1)
- {
- // 若不为帧头,复位指针
- if(Uart_R_Str[0] != Frame_Header)
- {
- R_curr = 0;
- R_num = 0;
- }
- }
- if(R_curr == 3) // 第二字节,通信帧长度
- R_num = Uart_R_Str[2]+1; // Uart_R_Str[1] 为通信帧长度
- // 每接收一个数据,num减1,当num为0时,一帧数据接收完毕
- if(R_num != 0)
- {
- R_num--;
- if(R_num == 0)
- {
- R_curr = 0; // 当前存储位置指向Uart_R_Str[0]
- Status.Bits.Uart_Status = 1; // 置Uart接收完一帧数据标志位
- }
- }
- }
- // 发送中断
- else if(SCI1SR1_TC == 1) // 发送完成标志
- {
- // 最后一个字节发送完成
- if(T_curr == Uart_T_Str[2]+3)
- {
- //SCI1CR2 &= 0XF7; // 关闭发送功能
- SCI1CR2 &= 0xBF;
- T_curr = 0; // 复位数据指针
- Status.Bits.Uart_R_Over = 0; // 发送完成
- }
- else
- SCI1DRL = Uart_T_Str[T_curr++];
- }
- }
- // ============================================================================
- // 主程序
- // ============================================================================
- /******************************全局变量**************************/
- volatile byte Uart_R_Str[Uart_R_Length]; // 串口接收数据缓冲区
- volatile byte Uart_T_Str[Uart_T_Length]; // 串口发送数据缓冲区
- /****************************************************************/
- void main(void)
- {
- // 初始化代码
- ...
- for(;;)
- {
- if(Status.Bits.Uart_Status)
- {
- Uart_Deal(); // 接收帧处理函数,功能:校验,解析帧。
- }
- if(Status.Bits.Uart_T_Commd && (!Status.Bits.Uart_R_Over))
- {
- Status.Bits.Uart_T_Commd = 0; // 清除发送请求命令位
- Send_1(); // 发送
- }
- // 其余代码
- ...
- }
- }
- //源地址链接:http://blog.csdn.net/finewind/article/details/5539541