how to send lin break?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

how to send lin break?

Jump to solution
1,693 Views
congminzhou
Contributor I

hi all:

I want to send lin break ,used MC9S12ZVL, my code:

 

//--------------------------------------------------------------------------------
//
//SCI0 Lin init 总线时钟 24MHZ 配置波特率:19200 KB/S
//-------------------------------------------------------------------------------
void init_SCI0(void)
{
SCI0SR2_AMAP = 0;//
SCI0ACR2_IREN = 0;//红外遥控解码 功能禁止

SCI0BD = 1250; // 波特率设置 24000000/1302 = 19201 =19.2K

//SCI0CR1 = 0x00; //SCI0 控制寄存器1配置
SCI0CR1_PT = 0; //奇偶校验位 0 偶校验, 1:奇校验 ,只有当PE =1,时有效
SCI0CR1_PE = 0; //奇偶校验使能位 0:禁止 1:使能
SCI0CR1_ILT = 0 ; //空闲线类型为 ,异步模式必须为0
SCI0CR1_WAKE = 0; //唤醒条件位,0:空闲线唤醒, 1:地址线唤醒
SCI0CR1_M = 0; //数据格式选择位 0:8位 1:9位
SCI0CR1_RSRC = 0; // SCI环路模式下的接收源选择位 ,只有当 LOOPS = 1,时才有效
SCI0CR1_SCISWAI = 0; //等待模式下的 停止位 0: 使能 1:禁止
SCI0CR1_LOOPS = 0; // 环路和正常模式选择位 0:正常模式

//-----------------------------------------------------------------


// SCI0CR2 = 0x2c; //SCI0 控制寄存器1配置

SCI0CR2_SBK = 0; //
SCI0CR2_RWU = 0; //
SCI0CR2_RE = 1; // 接收器接收使能位 1: 使能 0:禁止
SCI0CR2_TE = 1; // 发送器发送使能位 1: 使能 0:禁止
SCI0CR2_ILIE = 0; //
SCI0CR2_RIE = 1; //接收满中断使能
SCI0CR2_TCIE = 0; //
SCI0CR2_TIE = 0; // 发送完中断使能 ///ggg

LP0CR_LPE = 1; //LIN 处于普通收发模式
LP0CR_RXONLY = 0; //

RX_FLAGS.byte = 0; //接收标志复位

//---------------------------------------------------------
SCI0SR2_AMAP = 1;//
SCI0ACR1_BKDIE = 1;//2017 02 09 break interrupt enable
SCI0ACR2_BKDFE = 1;//break intrrupt LOGIC enable

SCI0SR2_RXPOL = 0;// edge active for falling
SCI0ACR1_RXEDGIE = 0; //

LP0CR_LPE = 1;//LIN physical init
LP0CR_LPWUE = 1;


}


//---------------------------------------------------------
//
//send break and 0x55
//--------------------------------------------------------
void send_break_hand(void)
{

SCI0SR2_BRK13 = 1; //13 BIT BREAK
SCI0CR2_SBK = 1; //START TO SEND

 

}

 

//-----------------------------------------------------------------------
//函数功能:system clock congfig 配置内晶振,使能PLL 得到 25Mhz总线频率
//入口参数:无
//出口参数:无
//----------------------------------------------------------------------
void init_OSC(void)
{
CPMUOSC_OSCE = 0; // 1:外晶体 使能 0:片内时钟
__asm (NOP);
__asm (NOP);
CPMUCLKS_PLLSEL =0; //不使能锁相环时钟,等配置好后再使能 rest =1

CPMUREFDIV_REFDIV0=0; //fREF = fIRCIM = 1M, 故 REFFRQ【1:0】 = 00
CPMUREFDIV_REFDIV1=0;

CPMUSYNR_SYNDIV0 = 1; // fvoc = 48M
CPMUSYNR_SYNDIV1 = 1; //由 fvoc = 2*fosc*(SYNDIV + 1) // SYNDIV = 23
CPMUSYNR_SYNDIV2 = 1; //
CPMUSYNR_SYNDIV3 = 0; //
CPMUSYNR_SYNDIV4 = 1; //
//CPMUSYNR_SYNDIV0 = 0; //0 = 0
// 48MHZ < fvco <= 64MHZ VCOFRQ[1:0] = 01
CPMUSYNR_VCOFRQ0 = 1;
CPMUSYNR_VCOFRQ1 = 0;

// CPMUIFLG_LOCK = 1; // if lock = 1

//fPLL = fvoc / (POSTDIV +1) //
//取 POSTDIV = 0 ===> fPLL = fvoc = 48Mhz
// fbusclock = fPLL/2 = 24MHZ
CPMUPOSTDIV_POSTDIV0 = 0;
CPMUPOSTDIV_POSTDIV1 = 0;
CPMUPOSTDIV_POSTDIV2 = 0;
CPMUPOSTDIV_POSTDIV3 = 0;
CPMUPOSTDIV_POSTDIV4 = 0;
__asm (NOP);
__asm (NOP);

while(CPMUIFLG_LOCK==0 ) //等待锁相环稳定
{
;
}
CPMUCLKS_PLLSEL = 1; //使能锁相环

ECLKCTL_NECLK = 0; //disable BUS CLOCK output on the ECLK PIN 0/1 ENABLI/DISABLE
//-----WATCHDOG ENABLE-----
CPMUCOP_CR2 = 1;
CPMUCOP_CR1 = 0;
CPMUCOP_CR0 = 0;


}


void main(void)
{
init_OSC( );

tim0ch0_init( );

init_SCI0( );

init_key( );
init_ad( );
init_pluse_io( );
init_moto( );
EnableInterrupts;
init_ram( );
send_break_hand( );

while(1)
{


}

}

 

 

but LIN BUS allways is hight ,why?

Labels (1)
Tags (1)
1 Solution
1,013 Views
RadekS
NXP Employee
NXP Employee

Hi Congmin,

I suppose, that your question is connected to the previous thread:

https://community.nxp.com/thread/451254

Correct?

 

We should toggle with SBK bit for transmitting break signal. For example:

SCI0CR2_SBK = 1; //START TO SEND

SCI0CR2_SBK = 0; //STOP SENDING BREAK

A break character contains all logic 0s and has no start, stop, or parity bit. As long as SBK is at logic 1, transmitter logic continuously loads break characters into the transmit shift register. After software clears the SBK bit, the shift register finishes transmitting the last break character and then transmits at least one logic 1. The automatic logic 1 at the end of a break character guarantees the recognition of the start bit of the next frame.

 

So, when we just set SBK bit without clearing SBK bit (as in the code in next thread), the SCI TX output will be kept in dominant level whole time. However, the LIN PHY has TxD-dominant timeout feature enabled by default. Therefore, the LIN transmitter will be shut down after a while and you will not see the dominant level at LIN pin.

Please check LPSR_LPDT flag.

 

There is the LIN stack:

http://www.nxp.com/assets/downloads/data/en/device-drivers/FSL_LIN_2.X_STACK.zip

 

The simple LIN example code for your inspiration (for the older S12G family) may be found here:

https://community.nxp.com/docs/DOC-93792

 

Other obvious and potential issues in your code:

  1. please be careful with read-modify-write commands like CPMUCOP_CR2 = 1;. Some of registers/bits can be written just once in normal mode (like the content of CPMUCOP register). So, the next commands will be ignored. I would like to recommend commands like CPUMCOP=0x04; for such registers. The CPUMCOP and MODRRx registers are the typical examples.
  2. You enabled COP watchdog. However, I do not see any for feeding it (write into CPMUARMCOP register).
  3. Commands

SCI0SR2_AMAP = 0;//

SCI0ACR2_IREN = 0;//红外遥控解码 功能禁止

doesn’t make sense, since SCI0ACR2_IREN bit is available only when you switch into the alternative map (AMAP=1).

  1. When you disable external oscillator (OSCE = 0), you cannot disable PLL. The PLL may be disabled only when clock from the external oscillator is enabled and validated (UPOSC=1). I would like to recommend from this reason also configure SYNR, REFDV, POSTDIV registers by single write – less confusion for PLL circuit.

I hope it helps you.

Have a great day,
Radek

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

View solution in original post

0 Kudos
3 Replies
1,013 Views
congminzhou
Contributor I

Hi Radek Sestak,

    Think you very much for your reply.now i send for loop mode, OK:

void send_break_hand(void)
{
// SCI0SR1_TDRE = 1;
//SCI0DRL = 0x00;

// SCI1CR1_M = 0;
//SCI0CR2_TE = 1; // 发送器发送使能位 1: 使能 0:禁止
//SCI0SR1_TC = 1;
SCI0CR1_LOOPS = 1; // 环路和正常模式选择位 0:正常模式
SCI0CR1_RSRC = 1; // SCI环路模式下的接收源选择位 ,只有当 LOOPS = 1,时才有效

SCI0SR2_BRK13 = 1; //13 BIT BREAK
SCI0CR2_SBK = 1; //START TO SEND

delay(1);
SCI0CR2_SBK = 0; //START TO SEND

SCI0CR1_LOOPS = 0; // 环路和正常模式选择位 0:正常模式
SCI0CR1_RSRC = 0; // SCI环路模式下的接收源选择位 ,只有当 LOOPS = 1,时才有效
SCI0DRL = 0X55;
read_back = SCI0DRL;
while(SCI0SR1_TC==0)
{
;

}
}

1,013 Views
RadekS
NXP Employee
NXP Employee

Hi Congmin,

I am glad that it works now correctly.

 

Just note: You don’t need delay(1); code.

When you set SBK bit, the transmit buffer will be filled with zeros. When you clear SBK bit, the transmitter will finish current task anyway.

Instead of this, I would like to recommend rather test/wait loop for TDRE bit prior start of any transmitting. For example:

while(!SCI0SR1_TDRE);                       //wait for transmit data register empty flag

SCI0CR2_SBK = 1; //START SENDING BREAK

SCI0CR2_SBK = 0; //STOP SENDING BREAK

or

while(!SCI0SR1_TDRE);                       //wait for transmit data register empty flag

SCI0DRL = 0X55;

 

The TDRE bit signalize whether TX buffer is ready for new data.

 

When we will use TDRE bit instead TC bit, the SCI throughput may be slightly higher – The TX buffer may be loaded prior previous transfer finish.

I hope it helps you.

Have a great day,
Radek

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

1,014 Views
RadekS
NXP Employee
NXP Employee

Hi Congmin,

I suppose, that your question is connected to the previous thread:

https://community.nxp.com/thread/451254

Correct?

 

We should toggle with SBK bit for transmitting break signal. For example:

SCI0CR2_SBK = 1; //START TO SEND

SCI0CR2_SBK = 0; //STOP SENDING BREAK

A break character contains all logic 0s and has no start, stop, or parity bit. As long as SBK is at logic 1, transmitter logic continuously loads break characters into the transmit shift register. After software clears the SBK bit, the shift register finishes transmitting the last break character and then transmits at least one logic 1. The automatic logic 1 at the end of a break character guarantees the recognition of the start bit of the next frame.

 

So, when we just set SBK bit without clearing SBK bit (as in the code in next thread), the SCI TX output will be kept in dominant level whole time. However, the LIN PHY has TxD-dominant timeout feature enabled by default. Therefore, the LIN transmitter will be shut down after a while and you will not see the dominant level at LIN pin.

Please check LPSR_LPDT flag.

 

There is the LIN stack:

http://www.nxp.com/assets/downloads/data/en/device-drivers/FSL_LIN_2.X_STACK.zip

 

The simple LIN example code for your inspiration (for the older S12G family) may be found here:

https://community.nxp.com/docs/DOC-93792

 

Other obvious and potential issues in your code:

  1. please be careful with read-modify-write commands like CPMUCOP_CR2 = 1;. Some of registers/bits can be written just once in normal mode (like the content of CPMUCOP register). So, the next commands will be ignored. I would like to recommend commands like CPUMCOP=0x04; for such registers. The CPUMCOP and MODRRx registers are the typical examples.
  2. You enabled COP watchdog. However, I do not see any for feeding it (write into CPMUARMCOP register).
  3. Commands

SCI0SR2_AMAP = 0;//

SCI0ACR2_IREN = 0;//红外遥控解码 功能禁止

doesn’t make sense, since SCI0ACR2_IREN bit is available only when you switch into the alternative map (AMAP=1).

  1. When you disable external oscillator (OSCE = 0), you cannot disable PLL. The PLL may be disabled only when clock from the external oscillator is enabled and validated (UPOSC=1). I would like to recommend from this reason also configure SYNR, REFDV, POSTDIV registers by single write – less confusion for PLL circuit.

I hope it helps you.

Have a great day,
Radek

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos