Not sure what you are expecting but running the following all I see in the output is 1:00 PM to 2:00 PM which corresponds to the LunchStart and LunchEnd for the sample student:
DECLARE @t TABLE
(StudId INT, StartDate datetime, EndDate datetime,StartTime datetime, EndTime datetime, LunchStart datetime,LunchEnd datetime,flag bit);
INSERT INTO @t
SELECT 555,'2012-01-01 00:00:00', '2012-01-02 00:00:00','2012-01-03 07:00:00', '2012-01-03 16:00:00','2012-01-03 13:00:00','2012-01-03 14:00:00',0;
WITH Tally1 (n) AS (
SELECT TOP 100
15 * (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1)
FROM
sys.all_columns
)
SELECT
StudId, LunchStart, LunchEnd,
dateadd(day, b.n-1, startdate) as effectivedate,
a.n,
b.n,
datediff(mi, LunchStart, LunchEnd)/15,
DATEDIFF(day, startdate,enddate) + 1,
Tstart = RIGHT(CONVERT(VARCHAR(100),dateadd(day, b.N-1, DATEADD(mi, (a.N-1)*15, LunchStart)), 0),7),
TsEnd = RIGHT(CONVERT(VARCHAR(100),dateadd(day, b.N-1, DATEADD(mi, a.N*15, LunchStart)), 0),7)
FROM @t
cross join Tally A
cross join Tally B
WHERE
a.N >= 1 and a.N <= datediff(mi, LunchStart, LunchEnd)/15 and
b.N >= 1 and b.N <= DATEDIFF(day, startdate,enddate) + 1
ORDER BY effectivedate ;
By the way, CTE's don't start with a semicolon (;). The semicolon is a statement TERMINATOR not a statement BEGININATOR and belongs on the statement immediately preceding the WITH of a CTE declaration.