MC9S12G128 SCI
Serial Communication Interface (SCI)
SCI异步串行通信:
术语词汇:
IR: InfraRed
IrDA: Infrared Design Associate
IRQ: Interrupt Request
LIN: Local Interconnect Network
LSB: Least Significant Bit
MSB: Most Significant Bit
NRZ: Non-Return-to-Zero
RZI: Return-to-Zero-Inverted
RXD: Receive Pin
SCI : Serial Communication Interface
TXD: Transmit Pin
功能框图:
相关寄存器:
SCI轮询方式收发数据代码:
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define D_BUSCLK_FREQ (16000000) // 总线频率 16MHz
#define D_SCI_BAUDRATE (9600) // 串口波特率
unsigned char txbuff[256]={0}; // 发送缓存
unsigned char rxbuff[256]={0}; // 接收缓存
/*************************************************************/
/* 串口发送函数 */
/*************************************************************/
void csi_send(unsigned char data)
{
while(!SCI0SR1_TDRE); //等待发送数据寄存器(缓冲器)为空
SCI0DRL = data;
}
void send_string(unsigned char *putchar)
{
while(*putchar!=0x00) //判断字符串是否发送完毕
{
csi_send(*putchar++);
}
}
unsigned char csi_receive(void)
{
while(!SCI0SR1_RDRF); //等待接收数据寄存器满
return(SCI0DRL);
}
/*************************************************************/
/** 定义了这个两个接口就可以使用printf函数格式化输出 **/
/** TERMIO_PutChar **/
/** TERMIO_GetChar **/
/*************************************************************/
void TERMIO_PutChar(char ch){
csi_send((unsigned char)ch);
}
char TERMIO_GetChar(void){
return (char)csi_receive();
}
void sci_init(void) {
SCI0BD = D_BUSCLK_FREQ/16/D_SCI_BAUDRATE; // 设置SCI0波特率 busCLK/16/BAUDRATE;
SCI0CR1 = 0x00; //设置SCI0为正常模式,八位数据位,无奇偶校验
SCI0CR2 = 0x08 | 0x04;//允许收发送数据,禁止中断功能 7:TIE, 6:TCIE, 5:RIE, 4:ILIE, 3:TE, 2:RE, 1:RWU, 0:SBK
}
/**
* @brief 锁相环 初始化
* @param none
* @return none
*/
void pll_init(void) {
CPMUPROT = 0x26; //保护时钟配置寄存器
CPMUCLKS_PSTP = 0; //禁用PLL
CPMUCLKS_PLLSEL = 1; //选择PLL作为系统时钟源
CPMUOSC_OSCE = 1; //外部晶振使能
while(CPMUOSC_OSCPINS_EN==0); //等待外部晶振使能
// BUSCLK = (PLLCLK / 2) 总线频率=(锁相环频率/2)
#if 1
//fVOC= 2*fOSC*(SYNDIV + 1)/(REFDIV + 1)
CPMUSYNR = 0x07;
//CPMUREFDIV = 0x0F; // PLLCLK:16M BUSCLK:8M
CPMUREFDIV = 0x07; // PLLCLK:32M BUSCLK:16M
//CPMUREFDIV = 0x03; // PLLCLK:64M BUSCLK:32M
#endif
#if 0
//fVOC配置 fVOC = 2*fREF*(SYNDIV +1)
//CPMUSYNR = 0x45; // PLLCLK:48M BUSCLK:24M
//CPMUSYNR = 0x44; // PLLCLK:40M BUSCLK:20M
//CPMUSYNR = 0x43; // PLLCLK:32M BUSCLK:16M
//CPMUSYNR = 0x42; // PLLCLK:24M BUSCLK:12M
CPMUSYNR = 0x01; // PLLCLK:16M BUSCLK:8M
CPMUREFDIV = 0x81;//REFDIV基准分频器配置
#endif
CPMUPOSTDIV = 0x00; // PLL CLOCK = VCO CLOCK / (POSTDIV + 1)
_asm(nop);
_asm(nop);
CPMUPLL=0x10; //锁相环调频启用,用以减少噪音
while(CPMUFLG_LOCK == 0); //等待PLL稳定
CPMUPROT = 0x00; //关闭保护时钟
CPMUCLKS_PLLSEL = 1; //使能PLL
}
void main(void) {
//int c;
/* put your own code here */
DisableInterrupts;
pll_init();
sci_init();
EnableInterrupts;
for(;;) {
/* TODO:单字符收发 */
rxbuff[0] = csi_receive(); // 接收一个字符 这里会阻塞
csi_send(rxbuff[0]+1); // 接收字符+1 并发送字符
csi_send('\n'); // 发送换行'\n'
/* TODO:发送字符串 */
(void)memset((char*)txbuff, 0, sizeof((char*)txbuff));
(void)sprintf((char*)txbuff, "%s", "This is freescale sci send.\n");
send_string(txbuff); // 发送字符串
/* TODO:printf 函数使用 */
(void)printf("sci test\n");
(void)printf("%s, %d\n","hello", 1234);
#if 0
c = getchar();
if (putchar(c)) {
} else {
}
#endif
_FEED_COP(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}
SCI中断方式收发数据代码:
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
#include <stdio.h>
#include <string.h>
#define D_BUSCLK_FREQ (16000000) // 总线频率 16MHz
#define D_SCI_BAUDRATE (9600) // 串口波特率
unsigned char txbuff[256]={0}; // 发送缓存
unsigned char rxbuff[256]={0}; // 接收缓存
unsigned char *send;
/*************************************************************/
/* 串口发送函数 */
/*************************************************************/
void csi_send(unsigned char data)
{
while(!SCI0SR1_TDRE); //等待发送数据寄存器(缓冲器)为空
SCI0DRL = data;
}
/*************************************************************/
/* 串口接收函数 */
/*************************************************************/
unsigned char csi_receive(void)
{
while(!SCI0SR1_RDRF); //等待发送数据寄存器满
return(SCI0DRL);
}
/*************************************************************/
/** 定义了这个两个接口就可以使用printf函数格式化输出 **/
/** TERMIO_PutChar **/
/** TERMIO_GetChar **/
/*************************************************************/
void TERMIO_PutChar(char ch){
csi_send((unsigned char)ch);
}
char TERMIO_GetChar(void){
return (char)csi_receive();
}
void sci_init(void) {
SCI0BD = D_BUSCLK_FREQ/16/D_SCI_BAUDRATE; // 设置SCI0波特率 busCLK/16/BAUDRATE;
SCI0CR1 = 0x00; //设置SCI0为正常模式,八位数据位,无奇偶校验 7:LOOPS 6:SCISWAI 5:RSRC 4:M 3:WAKE 2:ILT 1:PE 0:PT
SCI0CR2 = 0xAC; //允许收发数据,允许收发中断功能 7:TIE, 6:TCIE, 5:RIE, 4:ILIE, 3:TE, 2:RE, 1:RWU, 0:SBK
}
/**
* @brief 锁相环 初始化
* @param none
* @return none
*/
void pll_init(void) {
CPMUPROT = 0x26; //保护时钟配置寄存器
CPMUCLKS_PSTP = 0; //禁用PLL
CPMUCLKS_PLLSEL = 1; //选择PLL作为系统时钟源
CPMUOSC_OSCE = 1; //外部晶振使能
while(CPMUOSC_OSCPINS_EN==0); //等待外部晶振使能
// BUSCLK = (PLLCLK / 2) 总线频率=(锁相环频率/2)
#if 1
//fVOC= 2*fOSC*(SYNDIV + 1)/(REFDIV + 1)
CPMUSYNR = 0x07;
//CPMUREFDIV = 0x0F; // PLLCLK:16M BUSCLK:8M
CPMUREFDIV = 0x07; // PLLCLK:32M BUSCLK:16M
//CPMUREFDIV = 0x03; // PLLCLK:64M BUSCLK:32M
#endif
#if 0
//fVOC配置 fVOC = 2*fREF*(SYNDIV +1)
//CPMUSYNR = 0x45; // PLLCLK:48M BUSCLK:24M
//CPMUSYNR = 0x44; // PLLCLK:40M BUSCLK:20M
//CPMUSYNR = 0x43; // PLLCLK:32M BUSCLK:16M
//CPMUSYNR = 0x42; // PLLCLK:24M BUSCLK:12M
CPMUSYNR = 0x01; // PLLCLK:16M BUSCLK:8M
CPMUREFDIV = 0x81;//REFDIV基准分频器配置
#endif
CPMUPOSTDIV = 0x00; // PLL CLOCK = VCO CLOCK / (POSTDIV + 1)
_asm(nop);
_asm(nop);
CPMUPLL=0x10; //锁相环调频启用,用以减少噪音
while(CPMUFLG_LOCK == 0); //等待PLL稳定
CPMUPROT = 0x00; //关闭保护时钟
CPMUCLKS_PLLSEL = 1; //使能PLL
}
/*************************************************************/
/* 串口中断发送字符串函数 */
/*************************************************************/
#pragma CODE_SEG __NEAR_SEG NON_BANKED
interrupt VectorNumber_Vsci0 void sci_irq(void)
{
/* 字符收发 */
if (SCI0SR1_RDRF) {
rxbuff[0] = csi_receive(); // 接收数据
csi_send(rxbuff[0]); // 发送数据
}
/* TODO:发送字符串 */
if(*send!=0x00) { //判断字符串是否发送完毕
csi_send(*send++);
} else {
send = txbuff; //重新装载发送的数据
}
}
#pragma CODE_SEG DEFAULT
void main(void) {
/* put your own code here */
DisableInterrupts;
pll_init();
sci_init();
EnableInterrupts;
(void)memset((char*)txbuff, 0, sizeof((char*)txbuff));
(void)sprintf((char*)txbuff, "%s\n", "interrupt mode send and receive sci data");
(void)printf("************** CSI ****************\n");
for(;;) {
_FEED_COP(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}
printf函数使用:
/*************************************************************/
/** 定义了这个两个接口就可以使用printf函数格式化输出 **/
/** TERMIO_PutChar **/
/** TERMIO_GetChar **/
/*************************************************************/
void TERMIO_PutChar(char ch){
}
char TERMIO_GetChar(void){
}